Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a map to set parameters for a rest call using RestTemplate

I am currently using a piece of code to set parameters and I do a REST call to a URL using restTemplate, it works fine:

MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", grantType);
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
HttpEntity<?> entity = new HttpEntity<Object>(map);
restTemplate.exchange("myurl", HttpMethod.POST, entity, Void.class);

But if I am using a LinkedMultiValueMap it's because I looked on the web ;)

And if I replace it by a HashMap, it works as well, so can anyone tell me the advantage of using a LinkedMultiValueMap ?

Code with HashMap:

Map<String, String> map = new HashMap<String, String>();
map.put("grant_type", grantType);
map.put("client_id", clientId);
map.put("client_secret", clientSecret);
HttpEntity<?> entity = new HttpEntity<Object>(map);
restTemplate.exchange("myurl", HttpMethod.POST, entity, Void.class);

I can see we can preserve the order of the parameters in the LinkedMultiValueMap, but it does not matter in my project... And so if orders matters I still could use a LinkedHashMap

EDIT:

It looks like I need the MultiValueMap if I use APPLICATION_FORM_URLENCODED and HashMap, this code throw an exception :

Map<String, String> map = new HashMap<String, String>();
map.add("grant_type", grantType);
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<?> entity = new HttpEntity<Object>(map, headers);
restTemplate.exchange("myurl", HttpMethod.POST, entity, Void.class);

Exception:

org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/x-www-form-urlencoded]
        at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:784)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:530)
        at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:448)
        at uk.co.wowcher.marketplace.commons.rest.RestTemplateUtils.getForEntity(RestTemplateUtils.java:54)
        at uk.co.wowcher.marketplace.submission.service.ParameterService.getProductParameterVOs(ParameterService.java:38)
        at uk.co.wowcher.marketplace.submission.service.ParameterService$$FastClassBySpringCGLIB$$3f87231d.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
        at uk.co.wowcher.marketplace.submission.logging.MarketplaceLogger.logMethodCalls(MarketplaceLogger.java:27)
        at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
        at uk.co.xxx.marketplace.submission.service.ParameterService$$EnhancerBySpringCGLIB$$a52b80b.getProductParameterVOs(<generated>)
        at uk.co.xxx.marketplace.submission.service.SubmissionService.getAgreementData(SubmissionService.java:449)
       at uk.co.xxx.marketplace.submission.service.SubmissionService$$FastClassBySpringCGLIB$$92bbe798.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)

So, it looks like that setting some parameters with a HashMap is not a good idea at all... So I removed the accepted answer for now, waiting more explanation on this point... And I have the suitable converter (converters.add(new FormHttpMessageConverter());), I mean if I use a MultiValueMap I don't have the exception, so the HashMap is the problem!

like image 262
Emilien Brigand Avatar asked Jul 10 '15 14:07

Emilien Brigand


People also ask

How do you make a call with RestTemplate?

3.1. Let's start simple and talk about GET requests, with a quick example using the getForEntity() API: RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "http://localhost:8080/spring-rest/foos"; ResponseEntity<String> response = restTemplate. getForEntity(fooResourceUrl + "/1", String.

How do you pass URL and query parameters in Spring REST client?

Query parameters are passed after the URL string by appending a question mark followed by the parameter name , then equal to (“=”) sign and then the parameter value. Multiple parameters are separated by “&” symbol. The same parameters passed as URL parameters in the previous example are passed as Query parameters here.

How do you use RestTemplate getForObject?

The getForObject method fetches the data for the given response type from the given URI or URL template using HTTP GET method. To fetch data for the given key properties from URL template we can pass Object Varargs and Map to getForObject method. The getForObject returns directly the object of given response type.


1 Answers

The only real advantage of using a LinkedMultiValueMap over other Map implementations is that it can store multiple values.

This is useful if you need to pass multiple values for the same key (for instance, if you need to pass a set of form checkbox values).

See the JavaDoc here.

In your case, since you only have one value per key, you should be able to safely use a HashMap.

like image 115
aryn.galadar Avatar answered Nov 08 '22 10:11

aryn.galadar