2014-11-28 1 views
3

у меня есть некоторые проблемы в моем приложении, я посылаю запрос POST, но я не могу извлечь JSONObject в моем сервере, это код для отправки:получить JSONObject в POST с футболкой

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))); 

Попытка получить с:

@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); 

JSONObject сеть кажется пустым, на самом деле он не выполняет метод («Hello не печатается»), то ошибка, я получаю «Invalid тело запроса» (потому что JSONObject пуст Я думаю) .. Что случилось с моим кодом?

Хорошо, я понял, что проблема связана с обработкой Json, например, с использованием Gson. Это мой улучшенный код (упрощенный вариант) по предложению пользователей, но я до сих пор есть проблемы ..

стороне клиента:

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); 

    } 
} 

стороне сервера:

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(); 

    } 
} 

Я создал GsonMessageBodyHandler.java в моем пакете с кодом, предложенным ниже пользователем peeskillet. Добавлен jersey-container-grizzly2-http.jar в мой web-inf/lib (я не знаю, как правильно использовать Maven), но все равно не работает. Что мне не хватает?

+0

@peeskillet это потому, что я пишу прокси-сервер, который выступает в качестве сервера для входящего запроса и в качестве клиента OpenStack. Это не тот же ресурс, и проблема возникает раньше, потому что метод createNetwork не выполняется вообще. – rok

+0

Вы добавили модуль [JSON-P] (https://jersey.java.net/documentation/latest/media.html#json.json-p)? –

+0

На самом деле я не сделал, потому что я использую Gson .. есть ли какая-то проблема? – rok

ответ

0

Были ли у вас какие-либо запросы JSON успешно проанализированы? Это может быть, что вам нужно включить поддержку JSON в Джерси:

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

В противном случае, это может быть просто не суметь по вашему желанию, чтобы превратить тело сообщения в JSONObject здесь:

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

Да, Json работает, потому что у меня нет проблем с запросами GET (я использую Jersey 2.13). Я думаю, что вы правы, он каким-то образом не смог превратить тело сообщения в JsonObject, но почему? – rok

+0

Возможно ли, что он вызывает один из ваших других методов @Path? Иногда разрешение путей может быть немного противоречивым. – user384842

+0

Вызов моего другого пути дает то же самое – rok

2

В чтобы преобразовать JSON в Java-тип, необходимо выполнить для MessageBodyReader и MessageBodyWriter реализацию, чтобы сделать преобразование в и из. Поскольку вы используете JsonObject, который является типом GSON, вы можете увидеть this implementation. Существует проблема с реализацией, хотя, как метод readFrom не компилировать с Джерси 2. Вот фиксированная версия

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(); 
     } 
    } 
} 

Тогда мы просто должны зарегистрировать его как клиента и приложения. Я использую автономный тест, где вы можете увидеть конфигурацию здесь

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

Вот класс ресурса я использовал для теста

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(); 
    } 
} 

Вот полный тест, который требует 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(); 
    } 
} 

Все, что делает тест, это отправить JsonObject. Хотя нет никакого видимого преобразования в JSON, в любом из моего кода, это происходит за кулисами GsonMessageBodyHandler. Если вы посмотрите на класс GsonResource, вы можете увидеть, что методы ничего не делают, кроме как отправить JsonObject. В тесте клиента я прочитал ответ как String, и вы можете увидеть результат так же, как и тот, который был отправлен в первоначальном запросе.

+0

У меня все еще есть проблемы, вот что я сделал: создал GsonMessageBodyHandler.java в моем пакете, скопировав ваш код выше, а затем положил в свой код 'client = ClientBuilder.newClient(). register (GsonMessageBodyHandler.class); как на моих клиентских, так и на серверных классах. Метод сервера выполнен (я там вывел вывод отладки), но json пуст, на самом деле в клиентской консоли я вижу {"type": "jsonObject"} insead той, которую я отправляю. Btw Я собираюсь изменить свой вопрос, добавив новый код, который у меня есть, чтобы быть более ясным. – rok

1

Там простой способ получить JSONObject по типу com.google.gson.JsonObject с использованием запроса пост.

Я предполагаю, что все зависимости для com.google.gson, jersey и jax-rs уже добавлены.

На стороне сервера вам нужно иметь код, аналогичный ниже:

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(); 

Код выше отдыхает конечная точка определяется с пути/API/пудинга и принимает тело запроса в виде строки. После того, как вы получите Json как строку на стороне сервера, com.google.gson.JsonParser можно использовать для прямого преобразования в com.google.gson.JsonObject, и это может быть использовано в вашей программе.

Чтобы сделать запрос на стороне сервера Вы отправляете запрос должен выглядеть следующим образом:

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" 
     }, 
} 
Смежные вопросы