Please recommend the optimal approach for parsing urlencoded or JSON-encoded responses when using Jetty HttpClient.
For example, I have created the following utility class for sending ADM-messages and use BufferingResponseListener
there, with UrlEncoded.decodeUtf8To
(for parsing bearer token response) and JSON.parse
(for parsing message sending response):
private final HttpClient mHttpClient;
private final String mTokenRequest;
private String mAccessToken;
private long mExpiresIn;
public Adm(HttpClient httpClient) {
mHttpClient = httpClient;
MultiMap<String> params = new MultiMap<>();
params.add("grant_type", "client_credentials");
params.add("scope", "messaging:push");
params.add("client_id", "amzn1.application-oa2-client.XXXXX");
params.add("client_secret", "XXXXX");
mTokenRequest = UrlEncoded.encode(params, null, false);
}
private final BufferingResponseListener mMessageListener = new BufferingResponseListener() {
@Override
public void onComplete(Result result) {
if (!result.isSucceeded()) {
if (result.getResponse().getStatus() % 100 == 4) {
String jsonStr = getContentAsString(StandardCharsets.UTF_8);
Map<String, String> resp = (Map<String, String>) JSON.parse(jsonStr);
String reason = resp.get("reason");
if ("AccessTokenExpired".equals(reason)) {
postToken();
} else if ("Unregistered".equals(reason)) {
// delete the invalid ADM registration id from the database
}
}
return;
}
String jsonStr = getContentAsString(StandardCharsets.UTF_8);
Map<String, String> resp = (Map<String, String>) JSON.parse(jsonStr);
String oldRegistrationId = (String) result.getRequest().getAttributes().get("registrationID");
String newRegistrationId = resp.get("registrationID");
if (newRegistrationId != null && !newRegistrationId.equals(oldRegistrationId)) {
// update the changed ADM registration id in the database
}
}
};
private final BufferingResponseListener mTokenListener = new BufferingResponseListener() {
@Override
public void onComplete(Result result) {
if (result.isSucceeded()) {
String urlencodedStr = getContentAsString(StandardCharsets.UTF_8);
MultiMap<String> params = new MultiMap<>();
UrlEncoded.decodeUtf8To(urlencodedStr, params);
long now = System.currentTimeMillis() / 1000;
mExpiresIn = now + Long.parseLong(params.getString("expires_in"));
mAccessToken = params.getString("access_token");
}
}
};
public void postMessage(String registrationId, int uid, String jsonStr) {
long now = System.currentTimeMillis() / 1000;
if (mAccessToken == null || mAccessToken.length() < 32 || mExpiresIn < now) {
postToken();
return;
}
mHttpClient.POST(String.format("https://api.amazon.com/messaging/registrations/%1$s/messages", registrationId))
.header(HttpHeader.ACCEPT, "application/json")
.header(HttpHeader.CONTENT_TYPE, "application/json")
.header(HttpHeader.AUTHORIZATION, "Bearer " + mAccessToken)
.header("X-Amzn-Type-Version", "com.amazon.device.messaging.ADMMessage@1.0")
.header("X-Amzn-Accept-Type", "com.amazon.device.messaging.ADMSendResult@1.0")
.attribute("registrationID", registrationId)
.content(new StringContentProvider(jsonStr))
.send(mMessageListener);
}
private void postToken() {
mHttpClient.POST("https://api.amazon.com/auth/O2/token")
.header(HttpHeader.ACCEPT, "application/json")
.header(HttpHeader.CONTENT_TYPE, "application/x-www-form-urlencoded")
.content(new StringContentProvider(mTokenRequest))
.send(mTokenListener);
}
The above class works okay, but seeing that there are Jetty-methods with InputStream in
arguments, like
and
JSON.parse(java.io.InputStream in)
I wonder if there is a smarter way to fetch and parse... maybe with something more effective than BufferingResponseListener
?
In other words my question is please:
How to use the "streaming" version of the above parsing methods with HttpClient
?