Search code examples
javarestarraylistjersey-client

How can I transfer an ArrayList<Map> via REST?


Edit: I tried to implement the suggestions of @Durgpal Singh and @Nikhil. I changed the code so it looks like this.

Client:

    Client client = ClientBuilder.newClient();
    WebTarget target = client
            .target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));

    Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
    Response response = invocationBuilder.get();

Map<String, List<Map>> result_ = response.readEntity(new GenericType<Map<String, List<Map>>>() { });
result = (ArrayList<Map>) result_.get("data");

Server:

ArrayList<Map> result;

result = new Ls3Algorithm().execute(new File("petrinetze").getAbsolutePath(), k, theta);

Map<String, List<Map>> map = new HashMap<>();
map.put("data", result);        
return Response.ok(map).build();

Unfortunately this leads to Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<java.lang.String, java.util.List<java.util.Map>>.

Where do I go wrong?

-------------------------------

I'm pretty new to RESTful web services and currently writing a microservice which provides a calculating algorithm. I'm testing the service as posted below.

Workflow: Client saves some data in a MongoDB database and sends the names of the relevant files via @PathParam as part of the GET request. The server then retrieves the files from the MongoDB, processes its algorithm and sends back the result as List<Map> packed in a Response object.

Goal: Transfer the result (List<Map>) as JSON and print it out on the client console.

Client:

package ls3test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Map;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;

public class Ls3TransmissionTest {
    final static String petrinets = "eins, zwei, drei, vier";
    final static int k = 3;
    final static float theta = 0.9f;

    public static void main(String[] args) throws IOException {

        [... save all the relevant files in the MongoDB ...]    

        ArrayList<Map> result = new ArrayList<Map>();

        Client client = ClientBuilder.newClient();
        WebTarget target = client
                .target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));

        Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
        Response response = invocationBuilder.get();

        result = response.readEntity(new GenericType<ArrayList<Map>>() {
        });

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        String json = ow.writeValueAsString(result);
        }
}

Server:

package service;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

@SuppressWarnings("deprecation")
@Path("/ls3algorithm")
public class Resource {

    // SLF4J is provided with Dropwizard
    Logger log = LoggerFactory.getLogger(Resource.class);

    @SuppressWarnings("rawtypes")
    @GET
    @Path("/{petrinets}/{k}/{theta}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response ls3execute(@PathParam("petrinets") String petrinetNames, @PathParam("k") int k,
            @PathParam("theta") float theta) {

        [... get all the relevant files from the MongoDB ...]

        List<Map> result;
        Ls3Algorithm ls3Algorithm = new Ls3Algorithm();

        result = ls3Algorithm.execute(new File("petrinetze").getAbsolutePath(), k, theta);

        GenericEntity<List<Map>> entity = new GenericEntity<List<Map>>(result) {};
        Response response = Response.ok(entity).build();

        return response;
    }
}

This is not working, the exception I get is posted below:

Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.ArrayList<java.util.Map>.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:231)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:834)
    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
    at org.glassfish.jersey.client.InboundJaxrsResponse$2.call(InboundJaxrsResponse.java:126)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
    at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:267)
    at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:123)
    at ls3test.Ls3TransmissionTest.main(Ls3TransmissionTest.java:89)

Ls3TransmissionTest.java:89 is ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();

I spent plenty of time now doing research on this problem, but I cannot find an example that really fits it. What do I miss? Any help or hint is highly appreciated!


Solution

  • You can send a map. Like this

    Map<String, Object> map = new HashMap<>();
    map.put("data", entity);
    Response.ok(map).build();
    return Response;