Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

We had several different ways to specify URLs that were used to call other services. This caused confusion when you were searching for what consumers existed for a particular service endpoint. One of our developers introduced us to UriBuilder and it was adopted. A simple example of UriBuilder usage is

URI myServiceUri = UriBuilder.fromPath(myServiceUrl)
                             .path("/path")
                             .build()
                             .toUri();

This will create a URI object which is directly usable by Spring’s RestTemplate.

  • .build(), .build(false) – builds the UriComponents object, but does not encode the values.
  • .build(true) – builds the UriComponents object and encodes the values.

UriBuilder also supports path variables and uses the same notation that Spring MVC uses for it’s controller mappings. In this example, we have a path variable that is specified with a placeholder and it’s encoded value is used to replace the placeholder.

URI myServiceUri = UriBuilder.fromPath(myServiceUrl)
                             .path("/path/{pathVariable}")
                             .buildAndExpand(pathVariable)
                             .encode()
                             .toUri();

Things just got interesting. If you have a value that you need substituted, then you need to call several methods.

  • .buildAndExpand() will allow you to expand data in the order that they were specified.
  • .encode() is needed to encode the data because .buildAndExpand() calls .build(false). .encode() optionally accepts encoding rulesl
  • toUri() to converts the return of encode() to an URI object.

If you specify multiple path variables and their values, they will be substituted in the order provided, as you would expect.

You can even specify query parameters with the following notation.

URI myServiceUri = UriBuilder.fromPath(myServiceUrl)
                             .path("/path/")
                             .queryParam("param1", param1)
                             .queryParam("param2", param2)
                             .build(true)
                             .toUri();

While, multiple values for the same request parameter isn’t common, it is supported by UriBuilder by simply specifying multiple values like so

URI myServiceUri = UriBuilder.fromPath(myServiceUrl)
                             .path("/path/")
                             .queryParam("param1", param1value1, param1value2)
                             .queryParam("param2", param2)
                             .build(true)
                             .toUri();

This will cause multiple parameters to be specified on the URL, each with it’s own value, like

param1=abc&param1=xyz

There are several UrlBuilder classes available in Java. We settled on javax.ws.rs.core because it is generally available no whatever what APIs you happen to be using in your project.

Along the way, we also came up with some standards for usage that go above and beyond what UriBuilder requires.

fromPath – We standardized on using the name of the application and Url as a suffix for the name of the variable containing the server that we are calling. This made it easy to find all calls to a particular system.

path – We standardized on using the same path value that we use in our Spring MVC controller. This made it easy for us to find the calls for any particular controller endpoint. As part of this, we also did away with using multiple Spring MVC mappings to create one mapping (e.g. annotating the top of a class and having that appended onto each method’s mapping). This created a bit of redundancy, but paid off dividends whenever we needed to find the clients of a service.

February 5th, 2019

Posted In: Javaninja

Tags: , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

WP to LinkedIn Auto Publish Powered By : XYZScripts.com