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

18,089

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.

Share:
18,089
Emilien Brigand
Author by

Emilien Brigand

I m working on JEE tech since 7 years and I like it :)

Updated on July 26, 2022

Comments

  • Emilien Brigand
    Emilien Brigand almost 2 years

    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!