2016-01-19 94 views
0

我在Google App Engine(1.9.30)上使用Google Http Client庫(1.20)向Google Cloud Messaging(GCM)服務器提交POST請求。這裏是代碼:爲什麼JsonHttpContent的輸出是空的?

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類(使用龍目生成getter和setter):

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

眼前的目標是產生如下(從Checking the validity of an API key)同樣的反應:使用curl所以

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"}]} 

我已經測試我知道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 in 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>作爲第二個參數,這樣就可以了,你希望它。

2

您需要@Key註釋的POJO領域:

import com.google.api.client.util.Key; 

// ... 

@Key private String to; 
@Key private Object data; 
@Key private List<String> registration_ids; 

// ...