Search code examples
javajava-8

Build URL/URI with 3 pieces (scheme, baseurl and suffix url) of information


I have 3 pieces of information that form a url/uri.

String myscheme = "https";
String basePath = "www.theothercompany.com";
String suffixPath = "/api/v1/things";

How do I "compose" a full URI or URL with (only) the three things above.

I've been through several constructors for : https://docs.oracle.com/javase/8/docs/api/java/net/URI.html and https://docs.oracle.com/javase/8/docs/api/java/net/URL.html

like I tried this:

   URI x = new URI(myscheme , basePath , suffixPath);

or

   URI y = new URI(myscheme , basePath , suffixPath, "");

But I keep getting things like

httpswww.theothercompany.comapi/v1/things

obviously, removing "parts" like "://" and "/".

I don't have a port, or a ssp or a user or textfile...or other things I saw in the constructors of the 2 above oracle links.

I can't believe this is roadblocking me !!

Below are some other (already) pulled in packages. I do not want to add another one (like org.apache.http.client.utils.URIBuilder for example).....to bloat the dependencies.

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;

and

compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: springBootVersion

compile group: 'org.apache.commons', name: 'commons-lang3', version: commonsLangVersion

compile 'org.projectreactor:reactor-spring:1.0.1.RELEASE'

APPEND

Ok, as per suggested, I fixed my mislabelling of the 3 parts.

   String myScheme = "https";
    String myHost = "www.theothercompany.com";
    String myPath = "/api/v1/things";

    java.net.URL computedFullUrl = null;
    String urlToStringValue = "";
    String urlToExternalFormValue = "";
    String urlToUriStringValue = "";
    try {

        /* this works....or does not exception out */
        computedFullUrl = new java.net.URL(myScheme, myHost, myPath);

        if (null != computedFullUrl) {
            urlToStringValue = computedFullUrl.toString();
            urlToExternalFormValue = computedFullUrl.toExternalForm();
            urlToUriStringValue = computedFullUrl.toURI().toString();
        }
    } catch (Exception ex) {
        //throw new RuntimeException((ex));
        // temporary swallow
        String temp = ex.getMessage();
        ex.printStackTrace();
    }

So the above works.

I get (all three "convert back to a full string" values of) :

https://www.theothercompany.com/api/v1/things

I finally figured it out.

It had nothing to do with URI or URL.

When i read the values from a property file, the beginning "/" was being stripped from "/api/v1/things"

The value in the string was "api/v1/things". (no quotes of course). That was my issue.

I'll leave the question up so others can learn from my faux pas.

Gaaaaaa.


Solution

  • The problem is partially caused by not using the correct technical terms:

    • www.theothercompany.com is a host name, not a “basePath”.
    • /api/v1/things is the path, not a “suffixPath”

    Obviously, you want to construct a hierarchical URI, but one of the constructors you use, is designed to construct an opaque URI¹, expecting the arguments scheme, ssp (scheme specific part), and fragment.

    The constructor’s documentation precisely describes the outcome:

    This constructor first builds a URI in string form using the given components as follows:

    1. Initially, the result string is empty.
    2. If a scheme is given then it is appended to the result, followed by a colon character (':').
    3. If a scheme-specific part is given then it is appended. Any character that is not a legal URI character is quoted.
    4. Finally, if a fragment is given then a hash character ('#') is appended to the string, followed by the fragment. Any character that is not a legal URI character is quoted.

    leading to https:www.theothercompany.com#/api/v1/things.

    Since you want to construct a hierarchical URI composed of scheme, host, and path, the second constructor is the right one:

    public URI​(String scheme, String host, String path, String fragment)

    Constructs a hierarchical URI from the given components.

    So using new URI(myscheme , basePath , suffixPath, "") leads to https://www.theothercompany.com/api/v1/things#.

    When you change it to new URI(myscheme , basePath , suffixPath, null), you’ll get https://www.theothercompany.com/api/v1/things.

    This demonstrates why named factories are preferable over overloaded constructors, as such a semantic difference between two constructors only differing by one parameter, is not very intuitive.


    ¹ or to construct a hierarchical URI by specifying the syntactical elements manually, which is rarely needed