31

I use Spring restTemplate. I made a REST service and client as unit test in separated application. I have method that return List of users and method for user creating:

@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON,
        MediaType.TEXT_XML })
@Path("/all")
public Response getAllUsers() {
    List<User> list = dao.getAll();
    GenericEntity<List<User>> result = new GenericEntity<List<User>>(list) {
    };
    return Response.status(Status.OK).entity(result).build();
}

If I request to show me all users in browser, it displays to me xml. It's OK. But, when I try to use this:

@Test
public void testGetAll() {
    List list = new RestTemplate().getForObject(URL + "all", List.class);
    System.out.println(list);
}

I got

WARNING: GET request for "http://localhost:8080/REST/all" resulted in 500 (Internal Server Error); invoking error handler

I tried to debug this. No exceptions during method works. And browser shows me the xml with users. What can be wrong?

Also, I want to know, how I can get status code or message from template object (for test)?

Thanks for your answers.

EDITED:

I modified my test method:

@Test
public void testGetAll() {
    RestTemplate template = new RestTemplate();

    List<HttpMessageConverter<?>> messageConverters = new    ArrayList<HttpMessageConverter<?>>();
    Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
    List<MediaType> mediaTypes = new ArrayList<MediaType>();
    mediaTypes.add(MediaType.APPLICATION_XML);
    jaxbMessageConverter.setSupportedMediaTypes(mediaTypes);
    messageConverters.add(jaxbMessageConverter);

    template.setMessageConverters(messageConverters);
    List list = template.getForObject(URL + "all",
            ArrayList.class);
    System.out.println(list);
}

And I got exception:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class java.util.ArrayList] and content type [application/xml]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:107)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:496)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:452)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:222)
at com.nixsolutions.web.service.rest.UserRESTServiceTest.testGetAll(UserRESTServiceTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
Oleksandr H
  • 2,965
  • 10
  • 40
  • 58
  • May be you need to specify content type you want to receive back? Since method produces 3 different content types, which one will be used to proceed with your request? – Admit Oct 18 '13 at 12:10
  • @Admit, I tried to do this, but I got an exception. I just update my question explaining that. – Oleksandr H Oct 18 '13 at 12:22
  • Will there be the same behaviour if you put `List` instead `ArrayList`, as it was previously. Another thing - may be you need some root element wrapping your collection. Some class which will have your collection as field and will be properly mapped using JaxB annotations. – Admit Oct 18 '13 at 12:29
  • Yes, behaviour the same. One different is that in stacktrace not [class java.util.ArrayList], but just List – Oleksandr H Oct 18 '13 at 12:36

4 Answers4

46

maybe this way ....

RestTemplate template = new RestTemplate(true);


ResponseEntity<TblGps[]> responseEntity = restTemplate.getForEntity(urlGETList, TblGps[].class);

TblGps[]=responseEntity.getBody();
kamokaze
  • 7,142
  • 5
  • 33
  • 43
7

You need to use a concrete implementation of List, for instance you can use ArrayList, see this example:

ResponseEntity<? extends ArrayList<User>> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<User>>)ArrayList.class, userId);

it even works for an entirely generic setup:

ResponseEntity<? extends ArrayList<HashMap<String,Object>>> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<HashMap<String,Object>>>)ArrayList.class, parameterId);
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
chrismarx
  • 11,488
  • 9
  • 84
  • 97
5

When you set the Jaxb2RootElementHttpMessageConverter you override the default converters that comes with RestTemplate. One of the default converters (I think that's the string converter) can handle text/xml type. Remove the whole Jaxb2RootElementHttpMessageConverter but leave that part when you expected ArrayList.class and not List.class and this will work:

@Test
public void testGetAll() {
    RestTemplate template = new RestTemplate();
    List list = template.getForObject(URL + "all",
        ArrayList.class);
    System.out.println(list);
}

You might also need to add an accept header to choose the use of text/xml and not one of the other produced types:

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(new MediaType[] {MediaType.TEXT_XML}));

And use exchange with RestTemplate (instead of getForObject):

List list = template.exchange(URL + "all", new HttpEntity<String>(requestHeaders()), ArrayList.class);
Avi
  • 21,182
  • 26
  • 82
  • 121
  • where I need to define requestHeaders and how to connect it with template? – Oleksandr H Oct 18 '13 at 13:51
  • @OleksandrHubachov - Sorry, I added another line of code that does that. – Avi Oct 18 '13 at 14:10
  • oh...I don't know what is the problem... i did this: HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.setAccept(Arrays .asList(new MediaType[] { MediaType.APPLICATION_XML })); ResponseEntity list = template.exchange(URL + "all", HttpMethod.GET, new HttpEntity( requestHeaders), ArrayList.class); but I still got the same exception... – Oleksandr H Oct 18 '13 at 14:34
  • Did you remove the converter definition? – Avi Oct 18 '13 at 16:14
  • @Avi I also have a similar question on RestTemplate [here](http://stackoverflow.com/questions/27749199/how-to-send-xml-data-as-an-input-parameter-with-url-using-resttemplate). If possible, can you help me out? – john Jan 02 '15 at 22:23
0

You could use restTemplate.getForEntity(). It will return you ResponseEntity with all response information(including status).

Admit
  • 4,897
  • 4
  • 18
  • 26
  • Good. It will solve one little problem. But I still can't extract list of users. I tried this: ResponseEntity list = template.getForEntity(URL + "all", ArrayList.class); but Could not extract response: no suitable HttpMessageConverter found for response type [class java.util.ArrayList] and content type [application/xml]. But I added application/xml as media type – Oleksandr H Oct 18 '13 at 12:49
  • look at my answer why are you using arraylist instaed of array of objects ...ResponseEntity responseEntity = restTemplate.getForEntity(urlGETList, TblGps[].class); and then TblGps[]=responseEntity.getBody(); – kamokaze May 15 '14 at 18:52