Spring Resttemplate Get with Parameters

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:

  1. getCustomer actually returns a JSONObject, not a Customer.
  2. templateURL hardcoded the base URL as well as the URL to customers.
  3. 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



Leave a reply



Submit