Spring RestTemplate GET with parameters
OK, so I'm being an idiot and I'm confusing query parameters with url parameters. I was kinda hoping there would be a nicer way to populate my query parameters rather than an ugly concatenated String but there we are. It's simply a case of build the URL with the correct parameters. If you pass it as a String Spring will also take care of the encoding for you.
RestTemplate: How to send URL and query parameters together
I would use buildAndExpand
from UriComponentsBuilder
to pass all types of URI parameters.
For example:
String url = "http://test.com/solarSystem/planets/{planet}/moons/{moon}";
// URI (URL) parameters
Map<String, String> urlParams = new HashMap<>();
urlParams.put("planet", "Mars");
urlParams.put("moon", "Phobos");
// Query parameters
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url)
// Add query parameter
.queryParam("firstName", "Mark")
.queryParam("lastName", "Watney");
System.out.println(builder.buildAndExpand(urlParams).toUri());
/**
* Console output:
* http://test.com/solarSystem/planets/Mars/moons/Phobos?firstName=Mark&lastName=Watney
*/
restTemplate.exchange(builder.buildAndExpand(urlParams).toUri() , HttpMethod.PUT,
requestEntity, class_p);
/**
* Log entry:
* org.springframework.web.client.RestTemplate Created PUT request for "http://test.com/solarSystem/planets/Mars/moons/Phobos?firstName=Mark&lastName=Watney"
*/
Spring RestTemplate - Passing in object parameters in GET
When you're using a complex object (like MyObj
) as a @RequestParam
, Spring will try to convert a string to that complex object. In this case, because MyObj
has only a single String
field called inputValue
it will automagically use whatever value you provide to your query parmeter to fill the property in your object.
For example, if you call: http://localhost:8080/get2?parm=foobar
you'll get a MyObj
where inputValue
will be "foobar"
.
If you use RestTemplate
you shouldn't get an error, but in stead it will try to convert new MyObj("Test input 2")
to a string, using the toString()
method and the response will be:
You entered com.example.MyObj@63a815e8
This is probably not what you want. Generally you don't want to pass complex objects as request parameters, you can use @RequestBody
with RequestMethod.POST
and restTemplate.postForEntity()
to properly pass your MyObj
as JSON.
Change your controller like this:
@RequestMapping(value = "/get2", method = RequestMethod.POST)
public ResponseEntity<String> get2(@RequestBody MyObj parm) {
String response = "You entered " + parm.getInputValue();
return new ResponseEntity<>(response, HttpStatus.OK);
}
And call it using RestTemplate
like this:
MyObj myObj = new MyObj("Test input 2");
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForEntity("http://localhost:8080/get2", myObj, String.class).getBody();
This will properly pass your object as JSON.
Best way to passing parameter to restTemplate.getForObject
First off, I would remove the else
branch and refactor the condition to:
public JSONObject getCustomer(final String customerId) {
if (isNull(customerId) || customerId.trim().isEmpty()) {
return null;
}
...
}
Second, if you have a bunch of URI variables, Spring guys recommend using a Map<String, String>
:
final String templateURL = "http://localhost:6061/customers/{customerId}";
final Map<String, String> variables = new HashMap<>();
variables.put("customerId", customerId);
...
template.getForObject(templateURL, String.class, variables);
Third, the method shouldn't create a RestTemplate
instance on its own. I would prefer injecting the already-tuned object into an instance field:
getTemplate().getForObject(templateURL, String.class, variables);
Finally, I would name the result
more meaningful:
final String customerRepresentation = ...;
Some notes:
getCustomer
actually returns aJSONObject
, not aCustomer
.templateURL
hardcoded the base URL as well as the URL to customers.- The method does a lot of work (takes too much responsibility) - argument validation, URL construction, making a request. Try to split these responsibilities between corresponding methods.
RestTemplate.exchange doesn't work properly. Missing params thrown
You are passing the query parameters (RequestParams) as headers.
Check the following example how to pass RequestParams:
public void findUserById()
{
String username = "chathuranga";
String password = "123";
Integer userId = 1;
String url = "http://localhost:" + port + "/users/" + userId;
//setting up the HTTP Basic Authentication header value
String authorizationHeader = "Basic " + DatatypeConverter.printBase64Binary((username + ":" + password).getBytes());
HttpHeaders requestHeaders = new HttpHeaders();
//set up HTTP Basic Authentication Header
requestHeaders.add("Authorization", authorizationHeader);
requestHeaders.add("Accept", MediaType.APPLICATION_JSON_VALUE);
//request entity is created with request headers
HttpEntity<AddUserRequest> requestEntity = new HttpEntity<>(requestHeaders);
//adding the query params to the URL
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("name", "chathuranga")
.queryParam("email", "chathuranga.t@gmail.com");
ResponseEntity<FindUserResponse> responseEntity = restTemplate.exchange(
uriBuilder.toUriString(),
HttpMethod.GET,
requestEntity,
FindUserResponse.class
);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
System.out.println("response received");
System.out.println(responseEntity.getBody());
} else {
System.out.println("error occurred");
System.out.println(responseEntity.getStatusCode());
}
}
How do I send a get request with path variables and query parameters using RestTemplate?
I fixed the problem using builder.buildAndExpand(carVariable).toUri()
The solution looks like this:
ResponseEntity<CarDetail> carDetails = restTemplate.exchange(
builder.buildAndExpand(carVariable).toUri(),
HttpMethod.GET,
requestEntity,
CarDetail.class);
Related Topics
In Java, When Does an Object Become Unreachable
How to Flatten 2D Array to 1D Array
Get the Changed HTML Content After It's Updated by JavaScript? (Htmlunit)
Load Resource from Anywhere in Classpath
Java, "Variable Name" Cannot Be Resolved to a Variable
How to Change the Shape of a Jtabbedpane Tab
What Does an Exclamation Mark Mean in Java
Why Converting from Float to Double Changes the Value
How to Add Unique Jcomboboxes to a Column in a Jtable (Java)
How to Get the Desktop Path in Java
How to Convert a String to Another Locale
Java Division by Zero Doesnt Throw an Arithmeticexception - Why
How to Solve "Java.Io.Ioexception: Error=12, Cannot Allocate Memory" Calling Runtime#Exec()