Get JsonObject in POST with jersey

I have some problems in my application, I am sending a POST request, but I cannot get the JsonObject on my server, this is the code to send:

String quo = "{\"network\": {\"label\": \"new net 111\",\"cidr\": \"10.20.105.0/24\"}}";
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
JsonParser json = new JsonParser();
JsonObject jo = (JsonObject)json.parse(quo);
ClientConfig config = new ClientConfig();

Client client = ClientBuilder.newClient(config);

WebTarget target = client.target("http://localhost:7999/jersey/rest/network/"+tenant_id);

Response oj = target.request().accept(MediaType.APPLICATION_JSON)
        .header("X-Auth-Token", token)
        .post(Entity.json(gson.toJson(jo)));

      

Trying to get with:

@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/{tenant_id}")
public String createNetwork(@HeaderParam(value = "X-Auth-Token") String authToken, 
                        @PathParam(value = "tenant_id") String tenant_id, 
                        JsonObject network){

    Response response = client.target(NOVA_ENDPOINT+tenant_id)
                .request(MediaType.APPLICATION_JSON)
                .header("X-Auth-Token", authToken)
                .post(Entity.json(gson.toJson(network)));
    System.out.println("Hello"); 
    String responseJson = response.readEntity(String.class);

      

The JsonObject net seems empty, it doesn't actually execute the method ("Hello is not print"), the error I get is "Invalid request body" (because the JsonObject is empty I guess). What's wrong with my code?

Ok, I figured out that the problem is with Json handling, like Gson. This is my improved code (simplified version) after users suggestion, but I still have problems.

Client side:

package openstack;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URI;


public class Post {

    public static HttpServer startServer() {
    final ResourceConfig resourceConfig = new ResourceConfig()
            .packages("openstack")
            .register(GsonMessageBodyHandler.class);
    return GrizzlyHttpServerFactory.createHttpServer(URI.create("http://localhost:7999/jersey/rest"), resourceConfig);
}  
    public static void main(String[] args) {

    String quo = "{\"keypair\": {\"name\": \"MyKey\"}}";
    HttpServer server = startServer();


    Client client = ClientBuilder.newClient();

    client.register(GsonMessageBodyHandler.class);

    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.create();
    JsonParser json = new JsonParser();
    JsonObject jo = (JsonObject)json.parse(quo);

    WebTarget target = client.target("http://localhost:7999/jersey/rest/test/prova");

    System.out.println(jo);
    Response oj = target.request().post(Entity.json(jo));

    String responseString = oj.readEntity(String.class);
    System.out.println(responseString);

    }
}

      

Server side:

package openstack;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

@Path("/test")
public class Test {

    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.create();
    Parliament parliament = new Parliament();
    JsonParser json = new JsonParser();
    private final Client client;

    public Test() {
        client = ClientBuilder.newClient().register(GsonMessageBodyHandler.class);
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/prova")
    public Response mymethod(JsonObject keypairsob){

        return Response.ok(keypairsob).build();

    }
}

      

In my package, I created a GsonMessageBodyHandler.java with the code suggested below by user peeskillet. Added jersey-container-grizzly2-http.jar to my web-inf / lib (I don't know how to use Maven correctly) but still doesn't work. What am I missing?

+3


source to share


3 answers


To convert JSON to a Java type, you need to do a for MessageBodyReader

and an MessageBodyWriter

implementation to convert to and from. Since you are using JsonObject

which is the GSON type you can see this implementation . There is an implementation issue though, since the method readFrom

doesn't compile with Jersey 2. Here is the fixed version

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;


@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public final class GsonMessageBodyHandler implements MessageBodyWriter<Object>,
        MessageBodyReader<Object> {

    private static final String UTF_8 = "UTF-8";

    private Gson gson;

    private Gson getGson() {
        if (gson == null) {
            final GsonBuilder gsonBuilder = new GsonBuilder();
            gson = gsonBuilder.create();
        }
        return gson;
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType,
            java.lang.annotation.Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public Object readFrom(Class<Object> type, Type type1, Annotation[] antns,
            MediaType mt, MultivaluedMap<String, String> mm, InputStream in) 
            throws IOException, WebApplicationException {
        InputStreamReader streamReader = new InputStreamReader(in, UTF_8);
        try {
            Type jsonType;
            if (type.equals(type1)) {
                jsonType = type;
            } else {
                jsonType = type1;
            }
            return getGson().fromJson(streamReader, jsonType);
        } finally {
            streamReader.close();
        }
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, 
            Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public long getSize(Object object, Class<?> type, Type genericType, 
            Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(Object object, Class<?> type, Type genericType, 
            Annotation[] annotations, MediaType mediaType, 
            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) 
            throws IOException, WebApplicationException {
        OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
        try {
            Type jsonType;
            if (type.equals(genericType)) {
                jsonType = type;
            } else {
                jsonType = genericType;
            }
            getGson().toJson(object, jsonType, writer);
        } finally {
            writer.close();
        }
    }
}

      

Then we just need to register it with both the client and the application. I am using a standalone test where you can see the configuration here.

final ResourceConfig resourceConfig = new ResourceConfig()
        .packages("jersey.stackoverflow.standalone")
        .register(GsonMessageBodyHandler.class);
...
Client c = ClientBuilder.newClient();
c.register(GsonMessageBodyHandler.class);

      

Here is the resource class I used for the test



import com.google.gson.JsonObject;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler;

@Path("/gson")
public class GsonResource {

    private final Client client;
    private static final String BASE_URI = "http://localhost:8080/api/gson";

    public GsonResource() {
        client = ClientBuilder.newClient().register(GsonMessageBodyHandler.class);
    }

    @POST
    @Path("/proxy")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response proxyPost(JsonObject json) {
        Response response = client.target(BASE_URI)
                .path("main-resource").request().post(Entity.json(json));
        JsonObject fromMainResource = response.readEntity(JsonObject.class);
        return Response.created(null /* should be a created URI */)
                .entity(fromMainResource).build();
    }

    @POST
    @Path("/main-resource")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response mainResource(JsonObject json) {
        return Response.ok(json).build();
    }  
}

      

Here's a complete test that requires this maven dependency

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import static jersey.stackoverflow.standalone.Main.BASE_URI;
import jersey.stackoverflow.standalone.provider.GsonMessageBodyHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.Test;

public class GsonProviderTest {

    public static HttpServer startServer() {
        final ResourceConfig resourceConfig = new ResourceConfig()
                .packages("jersey.stackoverflow.standalone")
                .register(GsonMessageBodyHandler.class);
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), resourceConfig);
    }

    public static Client getClient() {
        Client c = ClientBuilder.newClient();
        c.register(GsonMessageBodyHandler.class);
        return c;
    }

    @Test
    public void testGetIt() {
        HttpServer server = startServer();
        Client c = getClient();

        c.register(GsonMessageBodyHandler.class);

        String quo = "{\"network\": {\"label\": \"new net 111\",\"cidr\": \"10.20.105.0/24\"}}";

        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        JsonParser json = new JsonParser();
        JsonObject jo = (JsonObject) json.parse(quo);

        WebTarget target = c.target("http://localhost:8080/api/gson/proxy");
        Response response = target.request().post(Entity.json(jo));
        String responseString = response.readEntity(String.class);
        System.out.println(responseString);
        response.close();

        c.close();
        server.stop();
    }
}

      

All the test does is send JsonObject

. While there is no visible conversion to JSON, in any of my code this is happening behind the scenes GsonMessageBodyHandler

. If you look at the class GsonResource

, you can see that the methods do nothing but submit JsonObject

. In a client test, I read the response as a String and you can see the result the same as the one sent in the original request.

  • For more information on MessageBodyReaders and MessageBodyWriters see
+2


source


There is an easy way to get the JsonObject at com.google.gson.JsonObject using a post request.

I assume all dependencies for com.google.gson, jersey and jax-rs have already been added.

On the server side, you need to have code similar to below:

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/api")
public class JersyAPI {


    private JsonParser parser= new JsonParser();

    @POST
    @Path("/pudding")
    @Consumes("application/json")
    public Response postTest(String requestBody){
        Response re = Response.status(200).build();
        try{
            JsonObject inputObjectJson = parser.parse(requestBody).getAsJsonObject();

      



The above code has a resting endpoint defined with the path / api / pudding and it accepts the Request Body as a String. After you get the Json as a server side string, com.google.gson.JsonParser can be used to directly convert to com.google.gson.JsonObject and that can be used in your program.

To make a server side request, you send the request like this:

POST /rest/api/pudding HTTP/1.1
Host: localhost:8082
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: c2b087d9-4830-c8a8-2a19-78273a73898c

{
  "id": 1312312,
  "name": "Test",
  "data": { 
            "test" : "data"
        },
}

      

+1


source


Did you have any JSON requests successfully parsed? Perhaps you need to enable JSON support in Jersey:

https://jersey.java.net/documentation/1.18/json.html

Otherwise it might just be a failure on your request to include the post body in the JsonObject:

public String createNetwork(
    @HeaderParam(value = "X-Auth-Token") String authToken, 
    @PathParam(value = "tenant_id") String tenant_id, 
    JsonObject network)

      

0


source







All Articles