Почему вывод JsonHttpContent пуст?
Я использую клиентскую библиотеку Google Http (1.20) в Google App Engine (1.9.30) для отправки запроса POST на серверы Google Cloud Messaging (GCM). Вот код:
public static HttpRequestFactory getGcmRequestFactory() {
if (null == gcmFactory) {
gcmFactory = (new UrlFetchTransport())
.createRequestFactory(new HttpRequestInitializer() {
@Override
public void initialize(HttpRequest request) throws IOException {
request.getHeaders().setAuthorization(
"key=" + Config.get(Config.Keys.GCM_SERVER_API_KEY).orNull());
request.getHeaders().setContentType("application/json");
request.getHeaders().setAcceptEncoding(null);
}
});
}
return gcmFactory;
}
public static JsonFactory getJsonFactory() {
return jacksonFactory;
}
public static String sendGcmMessage(GcmDownstreamDto message) {
HttpRequestFactory factory = getGcmRequestFactory();
JsonHttpContent content = new JsonHttpContent(getJsonFactory(), message);
String response = EMPTY;
try {
HttpRequest req = factory.buildPostRequest(gcmDownstreamUrl, content);
log.info("req headers = " + req.getHeaders());
System.out.print("req content = ");
content.writeTo(System.out); // prints out "{}"
System.out.println(EMPTY);
HttpResponse res = req.execute(); // IOException here
response = IOUtils.toString(res.getContent());
} catch (IOException e) {
log.log(Level.WARNING, "IOException...", e);
}
return response;
}
Теперь content.writeTo()
всегда печатает пустой JSON. Это почему? Что я делаю неправильно? GcmDownstreamDto
класс (используя Lombok для генерации геттеров и сеттеров):
@Data
@Accessors(chain = true)
public class GcmDownstreamDto {
private String to;
private Object data;
private List<String> registration_ids;
private GcmNotificationDto notification;
public GcmDownstreamDto addRegistrationId(String regId) {
if (null == this.registration_ids) {
this.registration_ids = new ArrayList<>();
}
if (isNotBlank(regId)) {
this.registration_ids.add(regId);
}
return this;
}
}
Ближайшая цель состоит в том, чтобы сгенерировать тот же ответ, что и (из проверки правильности ключа API):
api_key=YOUR_API_KEY
curl --header "Authorization: key=$api_key" \
--header Content-Type:"application/json" \
https://gcm-http.googleapis.com/gcm/send \
-d "{\"registration_ids\":[\"ABC\"]}"
{"multicast_id":6782339717028231855,"success":0,"failure":1,
"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
Я уже тестировал с помощью curl
так что я знаю, что ключ API действителен, я просто хочу сделать то же самое в коде Java для создания моих базовых классов.
sendGcmMessage()
вызывается следующим образом:
@Test
public void testGcmDownstreamMessage() {
GcmDownstreamDto message = new GcmDownstreamDto().addRegistrationId("ABC");
System.out.println("message = " + message);
String response = NetCall.sendGcmMessage(message);
System.out.println("Response: " + response);
}
Вся помощь приветствуется.
2 ответа
Выяснил проблему: это путь JacksonFactory().createJsonGenerator().searialize()
работает (я ожидал, что сериализовать способ ObjectMapper
сериализует). Это код для JsonHttpContent.writeTo()
(из JsonHttpContent.java в google-http-java-client):
public void writeTo(OutputStream out) throws IOException {
JsonGenerator generator = jsonFactory.createJsonGenerator(out, getCharset());
generator.serialize(data);
generator.flush();
}
Джексон JsonGenerator
ожидает пары ключ-значение (представленные в Java как Map
), что не очевидно из сигнатуры конструктора JsonHttpContent
конструктор: JsonHttpContent(JsonFactory, Object)
,
Так что если вместо прохождения GcmDownstreamDto
(как определено в вопросе, который работал бы с ObjectMapper
), Я должен был сделать следующее:
Map<String, Object> map = new HashMap<>();
List<String> idList = Arrays.asList("ABC");
map.put("registration_ids", idList);
все работает как положено и вывод:
{"registration_ids":["ABC"]}
Так что просто не забудьте передать JsonHttpContent(JsonFactory, Object)
конструктор Map<String, Object>
как второй параметр, и все будет работать так, как вы ожидаете.
Вы должны аннотировать поля POJO с помощью @Key
:
import com.google.api.client.util.Key;
// ...
@Key private String to;
@Key private Object data;
@Key private List<String> registration_ids;
// ...