-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* batch api initial support for list of BoxAPIRequests * batch example and unit tests
- Loading branch information
Showing
43 changed files
with
871 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
src/example/java/com/box/sdk/example/BatchRequestExample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package com.box.sdk.example; | ||
|
||
import java.io.FileReader; | ||
import java.io.IOException; | ||
import java.io.Reader; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import com.box.sdk.BatchAPIRequest; | ||
import com.box.sdk.BoxAPIRequest; | ||
import com.box.sdk.BoxAPIResponse; | ||
import com.box.sdk.BoxConfig; | ||
import com.box.sdk.BoxDeveloperEditionAPIConnection; | ||
import com.box.sdk.BoxFolder; | ||
import com.box.sdk.BoxJSONRequest; | ||
import com.box.sdk.BoxJSONResponse; | ||
import com.box.sdk.BoxUser; | ||
import com.box.sdk.IAccessTokenCache; | ||
import com.box.sdk.InMemoryLRUAccessTokenCache; | ||
import com.box.sdk.http.HttpMethod; | ||
|
||
/** | ||
* | ||
*/ | ||
public final class BatchRequestExample { | ||
|
||
private static final int MAX_CACHE_ENTRIES = 100; | ||
private static final String APP_USER_NAME = "BATCH-TEST-APP-USER-NAME"; | ||
|
||
private BatchRequestExample() { } | ||
|
||
public static void main(String[] args) throws IOException { | ||
// Turn off logging to prevent polluting the output. | ||
Logger.getLogger("com.box.sdk").setLevel(Level.OFF); | ||
|
||
|
||
//It is a best practice to use an access token cache to prevent unneeded requests to Box for access tokens. | ||
//For production applications it is recommended to use a distributed cache like Memcached or Redis, and to | ||
//implement IAccessTokenCache to store and retrieve access tokens appropriately for your environment. | ||
IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES); | ||
|
||
Reader reader = new FileReader("src/example/config/config.json"); | ||
BoxConfig boxConfig = BoxConfig.readFrom(reader); | ||
|
||
BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection( | ||
boxConfig, accessTokenCache); | ||
|
||
List<BoxAPIRequest> requests = new ArrayList<BoxAPIRequest>(); | ||
|
||
//Get current user request | ||
URL getMeURL = BoxUser.GET_ME_URL.build(api.getBaseURL()); | ||
BoxAPIRequest getMeRequest = new BoxAPIRequest(getMeURL, HttpMethod.GET); | ||
requests.add(getMeRequest); | ||
|
||
//Create App User Request | ||
URL createUserURL = BoxUser.USERS_URL_TEMPLATE.build(api.getBaseURL()); | ||
BoxJSONRequest createAppUserRequest = new BoxJSONRequest(createUserURL, HttpMethod.POST); | ||
createAppUserRequest.setBody("{\"name\":\"" + APP_USER_NAME + "\",\"is_platform_access_only\":true}"); | ||
requests.add(createAppUserRequest); | ||
|
||
//Get Root Folder Request | ||
URL getRootFolderURL = BoxFolder.FOLDER_INFO_URL_TEMPLATE.build(api.getBaseURL(), 0); | ||
BoxAPIRequest getRootFolderRequest = new BoxAPIRequest(getRootFolderURL, HttpMethod.GET); | ||
requests.add(getRootFolderRequest); | ||
|
||
BatchAPIRequest batchRequest = new BatchAPIRequest(api); | ||
List<BoxAPIResponse> responses = batchRequest.execute(requests); | ||
|
||
System.out.println("GET ME RESPONSE:"); | ||
System.out.println("Response Code: " + responses.get(0).getResponseCode()); | ||
System.out.println("Response: " + ((BoxJSONResponse) responses.get(1)).getJSON()); | ||
|
||
System.out.println("CREATE APP USER RESPONSE:"); | ||
System.out.println("Response Code: " + responses.get(1).getResponseCode()); | ||
System.out.println("Response: " + ((BoxJSONResponse) responses.get(1)).getJSON()); | ||
|
||
System.out.println("GET ROOT FOLDER RESPONSE:"); | ||
System.out.println("Response Code: " + responses.get(2).getResponseCode()); | ||
BoxJSONResponse rootFolderResponse = (BoxJSONResponse) responses.get(1); | ||
BoxFolder.Info rootFolderInfo = new BoxFolder(api, rootFolderResponse.getJsonObject().get("id").asString()) | ||
.new Info(rootFolderResponse.getJsonObject()); | ||
System.out.println("Root Folder Created At: " + rootFolderInfo.getCreatedAt()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package com.box.sdk; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import com.box.sdk.http.HttpHeaders; | ||
import com.box.sdk.http.HttpMethod; | ||
import com.eclipsesource.json.JsonArray; | ||
import com.eclipsesource.json.JsonObject; | ||
import com.eclipsesource.json.JsonValue; | ||
|
||
/** | ||
* Used to make a bunch of HTTP Requests as a batch. Currently the number of requests that can be batched at once | ||
* is capped at <b>20</b> by the API layer. Also there are certain requests which <b>cannot</b> be performed | ||
* by Batch API. Check API documentation for more information. | ||
* | ||
* <p>The request itself is a BoxJSONRequest but extends it to provide additional functionality for aggregating | ||
* a bunch of requests and responding with multiple responses as if the requests were called individually</p> | ||
*/ | ||
public class BatchAPIRequest extends BoxJSONRequest { | ||
/** | ||
* Batch URL Template. | ||
*/ | ||
public static final URLTemplate BATCH_URL_TEMPLATE = new URLTemplate("batch"); | ||
private final BoxAPIConnection api; | ||
|
||
/** | ||
* Constructs an authenticated BatchRequest using a provided BoxAPIConnection. | ||
* @param api an API connection for authenticating the request. | ||
*/ | ||
public BatchAPIRequest(BoxAPIConnection api) { | ||
super(api, BATCH_URL_TEMPLATE.build(api.getBaseURL()), HttpMethod.GET); | ||
this.api = api; | ||
} | ||
|
||
/** | ||
* Execute a set of API calls as batch request. | ||
* @param requests list of api requests that has to be executed in batch. | ||
* @return list of BoxAPIResponses | ||
*/ | ||
public List<BoxAPIResponse> execute(List<BoxAPIRequest> requests) { | ||
this.prepareRequest(requests); | ||
BoxJSONResponse batchResponse = (BoxJSONResponse) send(); | ||
return this.parseResponse(batchResponse); | ||
} | ||
|
||
/** | ||
* Prepare a batch api request using list of individual reuests. | ||
* @param requests list of api requests that has to be executed in batch. | ||
*/ | ||
protected void prepareRequest(List<BoxAPIRequest> requests) { | ||
JsonObject body = new JsonObject(); | ||
JsonArray requestsJSONArray = new JsonArray(); | ||
for (BoxAPIRequest request: requests) { | ||
JsonObject batchRequest = new JsonObject(); | ||
batchRequest.add("method", request.getMethod()); | ||
batchRequest.add("relative_url", request.getUrl().toString().substring(this.api.getBaseURL().length() - 1)); | ||
//If the actual request has a JSON body then add it to vatch request | ||
if (request instanceof BoxJSONRequest) { | ||
BoxJSONRequest jsonRequest = (BoxJSONRequest) request; | ||
batchRequest.add("body", jsonRequest.getBodyAsJsonObject()); | ||
} | ||
//Add any headers that are in the request, except Authorization | ||
if (request.getHeaders() != null) { | ||
JsonObject batchRequestHeaders = new JsonObject(); | ||
for (RequestHeader header: request.getHeaders()) { | ||
if (header.getKey() != null && !header.getKey().isEmpty() | ||
&& HttpHeaders.AUTHORIZATION.equals(header.getKey())) { | ||
batchRequestHeaders.add(header.getKey(), header.getValue()); | ||
} | ||
} | ||
batchRequest.add("headers", batchRequestHeaders); | ||
} | ||
|
||
//Add the request to array | ||
requestsJSONArray.add(batchRequest); | ||
} | ||
//Add the requests array to body | ||
body.add("requests", requestsJSONArray); | ||
super.setBody(body); | ||
} | ||
|
||
/** | ||
* Parses btch api response to create a list of BoxAPIResponse objects. | ||
* @param batchResponse response of a batch api request | ||
* @return list of BoxAPIResponses | ||
*/ | ||
protected List<BoxAPIResponse> parseResponse(BoxJSONResponse batchResponse) { | ||
JsonObject responseJSON = JsonObject.readFrom(batchResponse.getJSON()); | ||
List<BoxAPIResponse> responses = new ArrayList<BoxAPIResponse>(); | ||
Iterator<JsonValue> responseIterator = responseJSON.get("responses").asArray().iterator(); | ||
while (responseIterator.hasNext()) { | ||
JsonObject jsonResponse = responseIterator.next().asObject(); | ||
BoxAPIResponse response = null; | ||
|
||
//Gather headers | ||
Map<String, String> responseHeaders = new HashMap<String, String>(); | ||
|
||
if (jsonResponse.get("headers") != null) { | ||
JsonObject batchResponseHeadersObject = jsonResponse.get("headers").asObject(); | ||
for (JsonObject.Member member : batchResponseHeadersObject) { | ||
String headerName = member.getName(); | ||
String headerValue = member.getValue().asString(); | ||
responseHeaders.put(headerName, headerValue); | ||
} | ||
} | ||
|
||
// Construct a BoxAPIResponse when response is null, or a BoxJSONResponse when there's a response | ||
// (not anticipating any other response as per current APIs. | ||
// Ideally we should do it based on response header) | ||
if (jsonResponse.get("response") == null) { | ||
response = | ||
new BoxAPIResponse(jsonResponse.get("status").asInt(), responseHeaders); | ||
} else { | ||
response = | ||
new BoxJSONResponse(jsonResponse.get("status").asInt(), responseHeaders, | ||
jsonResponse.get("response").asObject()); | ||
} | ||
responses.add(response); | ||
} | ||
return responses; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.