Darwin Airola
Darwin Airola

Reputation: 919

Restlet Client Receiving Array of LinkedHashMap Elements Instead of Array of Object Elements

Aloha.

I have a Restlet server application with a @Get method that is supposed to be returning Object[], but the client receives an Object[] with elements of type LinkedHashMap. Each of the received array's elements correspond to the respective elements of the objects that the server was supposed to send.

Here is the relevant part of my resource (interface) file:

@Get
public Object[] retrieve() ;

Here is the relevant portion of my server resource file:

public Object[] retrieve()
{

  User newUser = new User() ;
  newUser.firstName = "John" ;
  newUser.lastName = "Doe" ;

  Object[] objectArray = (Object[]) Array.newInstance( User.class, 1 ) ;
  objectArray[0] = newUser ;

  return objectArray ;

}

Here is the relevant portion of my client:

public static void main( String[] args ) throws Exception
{
  Object[] arrayOfObjects = (Object[]) clientResource.retrieve() ;   //  array of LinkedHashMap elements
}

I assume that obtaining the result that I desire to obtain is easily done, but I am still very new to the Restlet framework. Thus, can someone tell me what I am doing wrong and show me an example of how to correctly send an array of (JSON encoded) objects from the server?

Thanks, in advance.

Take care,
Darwin

==================================================================================

UPDATE

Per StaxMan's comment (below), I also tried returning a generic List, but this just resulted in an ArrayList of LinkedHashMap elements, not an ArrayList of the desired type of elements.

Here is the relevant part of my resource (interface) file:

@Get
public <T> List<T> retrieve() ;

Here is the relevant portion of my server resource file:

public <T> List<T> retrieve()
{
  List<T> list = ... ;
  return list ;
}

Here is the relevant portion of my client:

//  the following does not work, since the returned ArrayList's
//  elements are not User objects but LinkedHashMap objects:
User[] users = (User[]) ((ArrayList<User>)clientResource.<User>retrieve()).toArray( (User[])Array.newInstance(User.class,0) ) ;

Can anyone tell me how to obtain an Array or List or ArrayList of the objects that I want from the server, while still maintaining the generic (or even pseudo generic) nature of the server?

Thanks, in advance.

Upvotes: 0

Views: 936

Answers (2)

Yessy
Yessy

Reputation: 1352

restlet framework DO NOT support return the parameterized type because it only support Class<?> as parameter

restlet framework use org.restlet.service.ConverterService

public <T> T toObject(Representation source, Class<T> target, Resource resource) throws IOException {
    ................
}

but java Class<?> type is type-erasured, so ConverterService don't know how to deserialize the generic parameters

so pls

  1. return T[] instead of List<T>
  2. deserialze mannually if return other generic value type

for example

ListItem.java

public class ListItem {
    public int intVal;
    public String strVal;

    public ListItem(){}


    public ListItem(int intVal, String strVal) {
        this.intVal = intVal;
        this.strVal = strVal;
    }
}

ListTestServerResource.java

public class ListTestServerResource extends ServerResource {
    @Get
    public List<ListItem> getItemList() {
        return Arrays.asList(new ListItem(1,"a"), new ListItem(2, "b"));
    }
}

ExampleUnitTest.java

public class ExampleUnitTest {

    @Before
    public void setup() throws Exception {
        Component component = new Component();
        component.getServers().add(Protocol.HTTP, 8088);
        component.getClients().add(Protocol.FILE);
        component.getDefaultHost().attach("/v1/list", ListTestServerResource.class);
        component.start();
    }

    @Test
    public void addition_isCorrect() throws IOException {

        ClientResource clientResource = new ClientResource(new Context(), "http://127.0.0.1:8088/v1/list");

        // this won't work, return List<LinkedHashMap> actually
        List<ListItem> listItems = clientResource.get(List.class);

        // this work
        ListItem[] listItems1 = clientResource.get(ListItem[].class);

        // this work also
        JacksonRepresentation jacksonRepresentation = clientResource.get(JacksonRepresentation.class);
        List<ListItem> listItems2 = jacksonRepresentation.getObjectMapper().readValue(jacksonRepresentation.getStream(), new TypeReference<List<ListItem>>() {
        });

        // this work also
        InputStream inputStream = clientResource.get(InputStream.class);
        List<ListItem> listItems3 = new ObjectMapper().readValue(inputStream, new TypeReference<List<ListItem>>() {
        });


        System.out.println(listItems1);
        System.out.println(listItems2);
        System.out.println(listItems3);
    }
}

Upvotes: 0

StaxMan
StaxMan

Reputation: 116600

This is because a List is a java.lang.Object -- you asking for a List of Objects and that you are getting. Without additional type information, that is pretty much all you could possibly get. In your case, you should rather return User[] (or List<User>)

Upvotes: 0

Related Questions