java.lang. IllegalArgumentException: URI is not absolute occurs when a relative url is used to identify the resource. In the spring boot RestTemplate, the complete url will be used to invoke the rest call. If the relative url is used in the restful call, the java exception java.lang. IllegalArgumentException: URI is not absolute would be thrown.
A resource can be invoked in java using a complete url. If the relative url is used, the relative url can not be converted to an absolute url. Therefore, the resource can’t be identified. The exception URI is not absolute will be thrown.
Exception
The exception java.lang. IllegalArgumentException: URI is not absolute stack trace will be shown as below in the spring boot. The root cause will be thrown from the java.
2020-10-06 17:15:08.417 ERROR 20534 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: URI is not absolute] with root cause
java.lang.IllegalArgumentException: URI is not absolute
at java.net.URI.toURL(URI.java:1088) ~[na:1.8.0_101]
at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145) ~[spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:124) ~[spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:735) ~[spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE]
How to recreate this exception
If a relative url is sent to a rest call in the RestTemplate, a relative url can not be converted to an absolute url. This is why the exception “java.lang.IllegalArgumentException: URI is not absolute” would be thrown. In the “/getstudent” rest call invokes another rest call using the relative url “/student”.
package com.yawintutor;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@GetMapping(value = "/student")
public Student getStudent() {
return new Student(1, "name1");
}
@GetMapping(value = "/getstudent")
private Student getStudentObject(HttpServletRequest request)
{
String uri = "/student";
RestTemplate restTemplate = new RestTemplate();
Student result = restTemplate.getForObject(uri, Student.class);
return result;
}
}
Solution 1
If a relative url is sent to a rest call in the RestTemplate, the relative url has to be changed to an absolute url. The RestTemplate will use the absolute url to identify the resource. In the example below, the complete url “http:/localhost:8080/student” is used to invoke a rest call using RestTemplate.
package com.yawintutor;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@GetMapping(value = "/student")
public Student getStudent() {
return new Student(1, "name1");
}
@GetMapping(value = "/getstudent")
private Student getStudentObject(HttpServletRequest request)
{
String uri = "http://localhost:8080/student";
RestTemplate restTemplate = new RestTemplate();
Student result = restTemplate.getForObject(uri, Student.class);
return result;
}
}
Solution 2
If you are using a relative url in a rest call that refers to the same tomcat server, use the HTTPRequest object to construct a complete url before submitting it to the rest template. The example below demonstrates how to create a complete url from the relative url to the same server.
package com.yawintutor;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@GetMapping(value = "/student")
public Student getStudent() {
return new Student(1, "name1");
}
@GetMapping(value = "/getstudent")
private Student getStudentObject(HttpServletRequest request)
{
String requestURL = request.getRequestURL().substring(0, request.getRequestURL().indexOf(request.getRequestURI()));
String uri = requestURL + "/student";
RestTemplate restTemplate = new RestTemplate();
Student result = restTemplate.getForObject(uri, Student.class);
return result;
}
}
Solution 3
If the relative url is used in RestTemplete that must be referred to an external host server, the external host server url can be externalized in the application.properties files. The properties can be added to the relative url as shown in the example below.
application.properties
external.server.url=http://www.yawintutor.com
TestController.java
package com.yawintutor;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Value("${external.server.url}")
String externalServerURL;
@GetMapping(value = "/student")
public Student getStudent() {
return new Student(1, "name1");
}
@GetMapping(value = "/getstudent")
private Student getStudentObject()
{
String uri = externalServerURL + "/student";
RestTemplate restTemplate = new RestTemplate();
Student result = restTemplate.getForObject(uri, Student.class);
return result;
}
}