markvgti markvgti - 8 months ago 32
Java Question

Why is JsonHttpContent's output empty?

I am using Google Http Client library (1.20) on Google App Engine (1.9.30) to submit a POST request to Google Cloud Messaging (GCM) servers. Here's the code:

public static HttpRequestFactory getGcmRequestFactory() {
if (null == gcmFactory) {
gcmFactory = (new UrlFetchTransport())
.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) throws IOException {
"key=" + Config.get(Config.Keys.GCM_SERVER_API_KEY).orNull());
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);"req headers = " + req.getHeaders());
System.out.print("req content = ");
content.writeTo(System.out); // prints out "{}"
HttpResponse res = req.execute(); // IOException here
response = IOUtils.toString(res.getContent());
} catch (IOException e) {
log.log(Level.WARNING, "IOException...", e);
return response;

Now the
always prints out empty JSON. Why is that? What am I doing wrong? The
class (using Lombok to generate getters and setters):

@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)) {
return this;

The immediate goal is to generate the same response as (from Checking the validity of an API key):


curl --header "Authorization: key=$api_key" \
--header Content-Type:"application/json" \ \
-d "{\"registration_ids\":[\"ABC\"]}"


I've already tested using
so I know the API key is valid, I just want to do the same thing in Java code to build up my base classes.

is being invoked as follows:

public void testGcmDownstreamMessage() {
GcmDownstreamDto message = new GcmDownstreamDto().addRegistrationId("ABC");
System.out.println("message = " + message);
String response = NetCall.sendGcmMessage(message);
System.out.println("Response: " + response);

All help appreciated.


Found out the problem: it's the way JacksonFactory().createJsonGenerator().searialize() works (I was expecting it to serialize the way ObjectMapper serializes). This is the code for JsonHttpContent.writeTo() (from in google-http-java-client):

public void writeTo(OutputStream out) throws IOException {
    JsonGenerator generator = jsonFactory.createJsonGenerator(out, getCharset());

The Jackson JsonGenerator expects a key-value pairing (represented in Java as Map) which is not obvious from the constructor signature of the JsonHttpContent constructor: JsonHttpContent(JsonFactory, Object).

So if instead of passing a GcmDownstreamDto (as defined in the question, which is what would have worked with an ObjectMapper), I were to do the following:

Map<String, Object> map = new HashMap<>();
List<String> idList = Arrays.asList("ABC");
map.put("registration_ids", idList);

everything works as expected and the output is:


So just remember to pass the JsonHttpContent(JsonFactory, Object) constructor a Map<String, Object> as the second parameter, and everything will work as you would expect it to.