From 951362ea505a11a826cf3acbb87809c2b40a45f7 Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Tue, 21 Oct 2025 02:19:59 -0700 Subject: [PATCH 1/3] chore: Update `.codegen.json` with commit hash of `codegen` and `openapi` spec [skip ci] --- .codegen.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codegen.json b/.codegen.json index 34541e444..1625d4e27 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "fa0419f", "specHash": "fa34496", "version": "10.1.0" } +{ "engineHash": "1aaaa3d", "specHash": "fa34496", "version": "10.1.0" } From 8066f2c8604c2969f4afcdf8ef91a4278c637550 Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Tue, 21 Oct 2025 09:20:18 -0700 Subject: [PATCH 2/3] chore: Update `.codegen.json` with commit hash of `codegen` and `openapi` spec [skip ci] --- .codegen.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codegen.json b/.codegen.json index 1625d4e27..aab5bc226 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "1aaaa3d", "specHash": "fa34496", "version": "10.1.0" } +{ "engineHash": "4a6585f", "specHash": "fa34496", "version": "10.1.0" } From 241d972649a098a263b0aa2704e38debbeffa4b8 Mon Sep 17 00:00:00 2001 From: box-sdk-build Date: Wed, 22 Oct 2025 05:51:20 -0700 Subject: [PATCH 3/3] docs: Add migration guides for Java (box/box-codegen#867) --- .codegen.json | 2 +- ...om-box-java-sdk-gen-v0-to-box-java-sdk.md} | 109 ++- .../from-com-box-sdk-to-com-box-sdkgen.md | 685 ++++++++++++++++++ migration-guides/from-v3-to-v4.md | 243 +++++++ migration-guides/from-v4-to-v10.md | 654 +---------------- migration-guides/from-v4-to-v5.md | 109 +++ migration-guides/from-v5-to-v10.md | 61 ++ 7 files changed, 1218 insertions(+), 645 deletions(-) rename migration-guides/{from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md => from-box-java-sdk-gen-v0-to-box-java-sdk.md} (59%) create mode 100644 migration-guides/from-com-box-sdk-to-com-box-sdkgen.md create mode 100644 migration-guides/from-v3-to-v4.md create mode 100644 migration-guides/from-v4-to-v5.md create mode 100644 migration-guides/from-v5-to-v10.md diff --git a/.codegen.json b/.codegen.json index aab5bc226..f674cde15 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "4a6585f", "specHash": "fa34496", "version": "10.1.0" } +{ "engineHash": "192deac", "specHash": "fa34496", "version": "10.1.0" } diff --git a/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk.md similarity index 59% rename from migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md rename to migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk.md index be55c1b75..33d6b8bc0 100644 --- a/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md +++ b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk.md @@ -1,8 +1,12 @@ -# Migration guide from beta release (v0.X.Y) of the `box-java-sdk-gen` to the v10 version of the `box-java-sdk` +# Migration guide from beta release (v0.X.Y) of the `box-java-sdk-gen` to the `box-java-sdk` + +Note: This guide applies only to migrations targeting Box Java SDK v5.X.Y or v10.X.Y. +It does not apply to other major versions (e.g., v6.X, v11.X). +- [Introduction](#introduction) - [Installation](#installation) - [How to migrate](#how-to-migrate) - [Maven](#maven) @@ -11,20 +15,39 @@ - [How to migrate](#how-to-migrate-1) - [Removed unused models from schemas namespace](#removed-unused-models-from-schemas-namespace) - [How to migrate](#how-to-migrate-2) +- [Usage](#usage) + - [Using the Box Java SDK v10](#using-the-box-java-sdk-v10) + - [Using the Box Java SDK v5](#using-the-box-java-sdk-v5) +## Introduction + +From the `box-java-sdk-gen` you can migrate either to v5 or v10 of the Box Java SDK. +Your choice should depend on whether you want to continue using the manually maintained SDK (Box Java SDK v4) alongside the generated one or not. + +The v5 version of the Box Java SDK consolidates both the legacy SDK package `com.box.sdk` and the generated one `com.box.sdkgen`. + +- If previously you were using both artifacts `box-java-sdk` v4 and `box-java-sdk-gen` v0, migrate to v5 version of the Box Java SDK which consolidates `com.box.sdk` and `com.box.sdkgen` packages. +- If you were only using the generated artifact `box-java-sdk-gen`, migrate to v10 version of the Box Java SDK which contains only the generated `com.box.sdkgen` package. + +| Scenario | Your current usage | Recommended target | Packages included in target | Why this choice | Notes | +| -------------------------------------------- | ---------------------------------------------------------- | ------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| Using both manual and generated SDK together | `com.box.sdk` v4 + `com.box.sdkgen` v0 in the same project | v5.X.Y | `com.box.sdk` (manual) + `com.box.sdkgen` (generated) | Keep existing v4 code while adopting new features from the generated SDK | Run both modules side by side; use type aliases to avoid name conflicts if necessary | +| Using only the generated SDK | `com.box.sdkgen` v0 only | v10.X.Y | `com.box.sdkgen` (generated) only | Clean upgrade path with no legacy module; simpler dependency surface | Best when you don’t need the manual `com.box.sdk` package | + ## Installation -In order to start using v10 version of the Box Java SDK, you need to change the dependency in your project. +In order to start using v5 or v10 version of the Box Java SDK, you need to change the dependency in your project. The artifact name has changed from `com.box:box-java-sdk-gen` to `com.box:box-java-sdk`. -You also need to set the version to `10.0.0` or higher. You can find the latest version on [Maven Central](https://search.maven.org/artifact/com.box/box-java-sdk). +You also need to set the version to `5.X.Y` if you are migrating to v5 or `10.X.Y` if you are migrating to v10. +You can find the latest version on [Maven Central](https://search.maven.org/artifact/com.box/box-java-sdk). ### How to migrate #### Maven -To start using v10 version of Box Java SDK in your Maven project replace the dependency in your `pom.xml` file. +To start using v5 or v10 version of Box Java SDK in your Maven project replace the dependency in your `pom.xml` file. **Old (`box-java-sdk-gen-v0`)** @@ -46,9 +69,19 @@ To start using v10 version of Box Java SDK in your Maven project replace the dep ``` +**New (`box-java-sdk-v5`)** + +```xml + + com.box + box-java-sdk + 5.0.0 + +``` + #### Gradle -To start using v10 version of Box Java SDK in your Gradle project replace the dependency in your `build.gradle` file. +To start using v5 or v10 version of Box Java SDK in your Gradle project replace the dependency in your `build.gradle` file. **Old (`box-java-sdk-gen-v0`)** @@ -62,6 +95,12 @@ implementation 'com.box:box-java-sdk-gen:0.8.0' implementation 'com.box:box-java-sdk:10.0.0' ``` +**New (`box-java-sdk-v5`)** + +```groovy +implementation 'com.box:box-java-sdk:5.0.0' +``` + ## Union classes name changes In the beta version of the `box-java-sdk-gen` our `OneOf` class names (representing unions from the OpenAPI specification) @@ -147,3 +186,63 @@ Here is the full list of removed types: | WorkflowFull | If your code references any of these types, remove those references. + +## Usage + +### Using the Box Java SDK v10 + +After migration from `box-java-sdk-gen` to the `box-java-sdk` v10, you can still use the `com.box.sdkgen` package in the same way as before. +To access the client for interacting with the Box API, simply import `BoxClient` and any other necessary classes from the `com.box.sdkgen` package. + +```java +import com.box.sdkgen.client.BoxClient; +import com.box.sdkgen.box.developertokenauth.BoxDeveloperTokenAuth; + +BoxDeveloperTokenAuth auth = new BoxDeveloperTokenAuth("DEVELOPER_TOKEN"); +BoxClient client = new BoxClient(auth); +client.folders.getFolderItems("0").getEntries().forEach(item -> { + System.out.println(item.toString()); + }); +``` + +### Using the Box Java SDK v5 + +After migration to Box Java SDK v5, you can use both the manual Box Java SDK package `com.box.sdk` and the generated one `com.box.sdkgen`. +You just need to import the required classes from the appropriate package depending on which SDK you intend to use. +If both packages contain classes with the same name, you can use fully qualified names to resolve any naming conflicts. + +```java +import com.box.sdk.BoxConfig; +import com.box.sdk.BoxDeveloperEditionAPIConnection; + +import com.box.sdk.BoxFolder; +import com.box.sdkgen.box.jwtauth.BoxJWTAuth; +import com.box.sdkgen.box.jwtauth.JWTConfig; +import com.box.sdkgen.client.BoxClient; +import com.box.sdkgen.managers.folders.UpdateFolderByIdRequestBody; +import com.box.sdkgen.schemas.folder.Folder; + +import java.io.FileReader; +import java.io.Reader; + +public class Main { + public static void main(String[] args) throws Exception { + + Reader reader = new FileReader("src/example/config/config.json"); + BoxConfig boxConfig = BoxConfig.readFrom(reader); + BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig); + + JWTConfig config = JWTConfig.fromConfigFile("src/example/config/config.json"); + BoxJWTAuth auth = new BoxJWTAuth(config); + BoxClient client = new BoxClient(auth); + + BoxFolder rootFolder = new BoxFolder(api, "0"); + BoxFolder.Info subfolder = rootFolder.createFolder("My Subfolder"); + Folder updatedFolder = client.getFolders().updateFolderById( + subfolder.getID(), + new UpdateFolderByIdRequestBody.Builder().name("My Updated Subfolder").build() + ); + System.out.println("Created folder with ID " + subfolder.getID() + " has been updated to " + updatedFolder.getName()); + } +} +``` diff --git a/migration-guides/from-com-box-sdk-to-com-box-sdkgen.md b/migration-guides/from-com-box-sdk-to-com-box-sdkgen.md new file mode 100644 index 000000000..54e72aa20 --- /dev/null +++ b/migration-guides/from-com-box-sdk-to-com-box-sdkgen.md @@ -0,0 +1,685 @@ +# Migration guide: migrate from `com.box.sdk` to `com.box.sdkgen` package + + + + +- [Introduction](#introduction) + - [Who is this for?](#who-is-this-for) +- [Key differences](#key-differences) + - [Manager approach](#manager-approach) + - [Immutable design](#immutable-design) + - [Consistent method signature](#consistent-method-signature) +- [Authentication](#authentication) + - [Developer Token](#developer-token) + - [JWT Auth](#jwt-auth) + - [Using JWT configuration file](#using-jwt-configuration-file) + - [Providing JWT configuration manually](#providing-jwt-configuration-manually) + - [Authenticate user](#authenticate-user) + - [Client Credentials Grant](#client-credentials-grant) + - [Obtaining Service Account token](#obtaining-service-account-token) + - [Obtaining User token](#obtaining-user-token) + - [Switching between Service Account and User](#switching-between-service-account-and-user) + - [OAuth 2.0 Auth](#oauth-20-auth) + - [Get Authorization URL](#get-authorization-url) + - [Authenticate](#authenticate) + - [Store token and retrieve token callbacks](#store-token-and-retrieve-token-callbacks) + - [Downscope token](#downscope-token) + - [Revoke token](#revoke-token) +- [Configuration](#configuration) + - [As-User header](#as-user-header) + - [Custom Base URLs](#custom-base-urls) +- [Convenience methods](#convenience-methods) + - [Webhook validation](#webhook-validation) + - [Chunked upload of big files](#chunked-upload-of-big-files) + + + +## Introduction + +Version availability: + +- v4: ships only `com.box.sdk` package +- v5: ships both `com.box.sdk` and `com.box.sdkgen` packages (side-by-side) +- v10+: ships only `com.box.sdkgen` module + +This document focuses on helping you migrate code from the manually maintained `com.box.sdk` package to the generated `com.box.sdkgen` package. +Many APIs were redesigned for consistency and modern Java patterns, so this guide calls out how to adopt the new shapes safely and incrementally. + +Supported migration paths: + +- v4 → v5: adopt `com.box.sdkgen` gradually while keeping existing `com.box.sdk` usage +- v4 → v10+: migrate directly to `com.box.sdkgen` package only +- v5 (within the same version): move usage from `com.box.sdk` to `com.box.sdkgen` gradually + +For comprehensive API docs with sample code for all methods, see the repository documentation in the root `docs` directory: [`docs/`](../docs/). + +We recommend using `com.box.sdkgen` as the preferred SDK going forward. This SDK is automatically generated from the +Box OpenAPI specification, ensuring consistency, reliability, and full API coverage. + +Key Benefits: + +- Comprehensive Coverage: Supports all Box API endpoints with consistent and predictable method signatures. +- Rapid Feature Availability: Automatically includes new features as soon as they are released in the Box API. +- Explicit Data Models: Includes clear, well-defined models for all API resources to improve readability and maintainability. +- Immutable Design: Built for immutability, making code behavior more predictable and easier to reason about. +- Rich Documentation: Offers detailed usage examples for every API method to help developers get started quickly. + +### Who is this for? + +- Developers with existing code using `com.box.sdk` who want to start using `com.box.sdkgen` APIs. +- Developers using v5 of Box Java SDK that want to transition usage from `com.box.sdk` to `com.box.sdkgen` within the same app. + +## Key differences + +### Manager approach + +The main difference between the manual `com.box.sdk` package and the nextgen generated one, +is the way how API methods are aggregated into objects. + +**Old (`com.box.sdk`)** + +Firstly, in the `com.box.sdk` to be able to perform any action on an API object, e.g. `User`, you first had to create its class. +To do it is required to call: + +```java +BoxUser user = new BoxUser(api, "12345"); +``` + +to create a class representing an already existing User with id '12345', or create a new one with a call: + +```java +BoxUser.Info createdUserInfo = BoxUser.createAppUser(api, "A User"); +BoxUser user = new BoxUser(api, createdUserInfo.getID()); +``` + +Then, you could perform any action on created class, which will affect the user, e.g. + +```java +BoxUser.Info info = user.new Info(); +info.setName(name); +user.updateInfo(info); +``` + +**New (`com.box.sdkgen`)** + +In the `com.box.sdkgen` package, the API methods are grouped into dedicated manager classes, e.g. `User` object +has dedicated `UserManager` class. Each manager class instance is available in `BoxClient` object. +The fields storing references to the managers are named in the plural form of the resource that the +manager handles - `client.users` for `UsersManager`. If you want to perform any operation +connected with a `User` you need to call a respective method of `UserManager`. +For example, to get info about existing user you need to call: + +```java +UserFull user = client.users.getUsersById("12345"); +``` + +or to create a new user: + +```java +CreateUserRequestBody requestBody = + new CreateUserRequestBody.Builder("John Doe").build(); +UserFull user = client.users.createUser(requestBody); +``` + +The `UserFull` object returned by both of these methods is a data class - it does not contain any methods to call. +To perform any action on `User` object, you need to still use a `UserManager` method for that. +Usually these methods have a first argument, which accepts id of the object you want to access, +e.g. to update a user name, call method: + +```java +UpdateUserByIdRequestBody requestBody = + new UpdateUserByIdRequestBody.Builder().name("Mary").build(); +UserFull updatedUser = client.users.updateUserById(user.getId(), requestBody); +``` + +### Immutable design + +The `com.box.sdkgen` is designed to be mostly immutable. This means that methods, +which used to modify the existing object in `com.box.sdk` now return a new instance of the class with the modified state. +This design pattern is used to avoid side effects and make the code more predictable and easier to reason about. +Methods, which returns a new modified instance of an object, will always have a prefix `with` in their names, e.g. + +**New (`com.box.sdkgen`)** + +```java +BoxClient client = new BoxClient(auth); +BoxClient asUserClient = client.withAsUserHeader("USER_ID"); +``` + +### Consistent method signature + +To facilitate easier work with the new SDK, we have changed the API method signatures to be consistent and unified. + +**Old (`com.box.sdk`)** + +In the manual version, API methods had numerous parameters, which were not grouped into any objects and were passed as separate arguments, e.g. the method for creating a sign request looked like this: + +```java +public static BoxSignRequest.Info createSignRequest(BoxAPIConnection api, List sourceFiles, + List signers, String parentFolderId, + BoxSignRequestCreateParams optionalParams) +``` + +**New (`com.box.sdkgen`)** + +In `com.box.sdkgen`, we have adopted an approach of aggregating parameters into types based on their nature (path, body, query, headers). +This can be seen in the example corresponding to the above: + +```java +public SignRequest createSignRequest( + SignRequestCreateRequest requestBody, CreateSignRequestHeaders headers) +``` + +According to the convention, if an API endpoint requires a parameter placed in the URL path, +it will appear at the beginning of our method, such as `fileId` in this case. +When a request allows for a body, as in `POST` or `PUT`, the method includes a parameter named `requestBody`. +Following that, the method signature may include the `queryParams` parameter, followed by `headers`. +The types of parameters `requestBody`, `queryParams`, and `headers` are specific to each endpoint and, in their definition, +encompass all fields allowed by the API. +It's worth noting here that when all fields of a particular type are optional, the entire parameter becomes optional as well. +This allows us to pass only the parameters we actually want to provide when calling a given method, +without the risk of not providing a sufficient number of parameters. + +## Authentication + +The `com.box.sdkgen` package offers the same authentication methods as the `com.box.sdk` one. +Let's see the differences of their usage: + +### Developer Token + +**Old (`com.box.sdk`)** + +```java +BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN"); +``` + +The `com.box.sdkgen` package provides a convenient `BoxDeveloperTokenAuth`, which allows authenticating +using developer token without necessity to provide a Client ID and Client Secret + +**New (`com.box.sdkgen`)** + +```java +BoxDeveloperTokenAuth auth = new BoxDeveloperTokenAuth("YOUR-DEVELOPER-TOKEN"); +BoxClient client = new BoxClient(auth); +``` + +### JWT Auth + +#### Using JWT configuration file + +**Old (`com.box.sdk`)** + +The static method, which reads the JWT configuration file has been changed: + +```java +Reader reader = new FileReader("src/example/config/config.json"); +BoxConfig boxConfig = BoxConfig.readFrom(reader); +IAccessTokenCache tokenCache = new InMemoryLRUAccessTokenCache(100); +BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig, tokenCache); +``` + +**New (`com.box.sdkgen`)** + +```java +TokenStorage tokenStorage = new InMemoryTokenStorage(); // or any other implementation of TokenStorage +JWTConfig config = JWTConfig.fromConfigFile("src/example/config/config.json", tokenStorage); +BoxJWTAuth auth = new BoxJWTAuth(config); +BoxClient client = new BoxClient(auth); +``` + +#### Providing JWT configuration manually + +Some params in `JWTConfig` constructor have slightly different names than one in old `JWTAuth` class. + +**Old (`com.box.sdk`)** + +```java +JWTEncryptionPreferences jwtPreferences = new JWTEncryptionPreferences(); +jwtPreferences.setPublicKeyID("PUBLIC-KEY-ID"); +jwtPreferences.setPrivateKeyPassword("PRIVATE-KEY-PASSWORD"); +jwtPreferences.setPrivateKey("PRIVATE-KEY"); +jwtPreferences.setEncryptionAlgorithm(EncryptionAlgorithm.RSA_SHA_256); + +IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(100); +BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection + .getUserConnection("USER-ID", "CLIENT-ID","CLIENT-SECRET", jwtPreferences, accessTokenCache); + +BoxUser.Info userInfo = BoxUser.getCurrentUser(api).getInfo(); +``` + +**New (`com.box.sdkgen`)** + +```java +TokenStorage tokenStorage = new InMemoryTokenStorage(); +JWTConfig config = new JWTConfig.Builder("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "JWT_KEY_ID", "PRIVATE_KEY", "PRIVATE_KEY_PASSWORD") + .enterpriseId("123456") + .tokenStorage(tokenStorage) + .build(); +BoxJWTAuth auth = new BoxJWTAuth(config); +BoxClient client = new BoxClient(auth); +``` + +#### Authenticate user + +In `com.box.sdk` package method for user authentication was named `BoxDeveloperEditionAPIConnection getUserConnection(String userId, BoxConfig boxConfig, IAccessTokenCache accessTokenCache)` +and was accepting user id. The method was returning a new instance of `BoxDeveloperEditionAPIConnection` class, which was exchanging the existing token with the one with the user access. + +**Old (`com.box.sdk`)** + +```java +BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getUserConnection("USER_ID", boxConfig, tokenCache); +``` + +**New (`com.box.sdkgen`)** + +In `com.box.sdkgen`, to authenticate as user you need to call +`public BoxJWTAuth withUserSubject(String userId, TokenStorage tokenStorage)` method with id of the user +to authenticate. The method returns a new instance of `BoxJWTAuth` class, which will perform authentication call +in scope of the user on the first API call. The `tokenStorage` parameter is optional and allows to provide a custom +token storage for the new instance of `BoxJWTAuth` class. The new auth instance can be used to create a new user client +instance. + +```java +BoxJWTAuth userAuth = auth.withUserSubject("USER_ID"); +BoxClient userClient = new BoxClient(userAuth); +``` + +### Client Credentials Grant + +#### Obtaining Service Account token + +To authenticate as enterprise, the only difference between `com.box.sdk` and `com.box.sdkgen` packages is using the `CCGConfig` as a middle step. + +**Old (`com.box.sdk`)** + +```java +BoxCCGAPIConnection api = BoxCCGAPIConnection.applicationServiceAccountConnection( + "client_id", + "client_secret", + "enterprise_id" +); +``` + +**New (`com.box.sdkgen`)** + +```java +CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET") + .enterpriseId("ENTERPRISE_ID") + .build(); +BoxCCGAuth auth = new BoxCCGAuth(config); +BoxClient client = new BoxClient(auth); +``` + +#### Obtaining User token + +To authenticate as user, the only difference between the versions is using the `CCGConfig` as a middle step. + +**Old (`com.box.sdk`)** + +```java +BoxCCGAPIConnection api = BoxCCGAPIConnection.userConnection( + "client_id", + "client_secret", + "user_id" +); +``` + +**New (`com.box.sdkgen`)** + +```java +CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET") + .userId("USER_ID") + .build(); +BoxCCGAuth auth = new BoxCCGAuth(config); +BoxClient client = new BoxClient(auth); +``` + +### Switching between Service Account and User + +In `com.box.sdk` package, if you want to switch between the Service Account and User, you need to create another API connection. + +In `com.box.sdkgen`, to keep the immutability design, the methods switching authenticated subject were replaced with methods +returning a new instance of `BoxCCGAuth` class. The new instance will fetch a new token on the next API call. +The new auth instance can be used to create a new client instance. You can also specify `tokenStorage` parameter +to provide a custom token storage for the new instance. +The old instance of `BoxCCGAuth` class will remain unchanged and will still use the old token. + +**New (`com.box.sdkgen`)** + +```java +BoxCCGAuth userAuth = auth.withUserSubject("USER_ID"); +BoxClient userClient = new BoxClient(userAuth); +``` + +```java +BoxCCGAuth entAuth = auth.withEnterpriseSubject("ENTERPRISE_ID"); +BoxClient entClient = new BoxClient(entAuth); +``` + +### OAuth 2.0 Auth + +#### Get Authorization URL + +To get authorization url in the `com.box.sdkgen` package, you need to first create the `BoxOAuth` class using +`OAuthConfig` class. Then to get authorization url, call `public String getAuthorizeUrl(GetAuthorizeUrlOptions options)`. +Note that this method accepts the instance of `GetAuthorizeUrlOptions` class, which allows specifying extra options to API call. + +**Old (`com.box.sdk`)** + +In `com.box.sdk`, we did not have any method to get the authorization URL. Instead, we had to manually create the URL. + +```java +String authorizationUrl = "https://account.box.com/api/oauth2/authorize?client_id=[CLIENT_ID]&response_type=code"; +``` + +**New (`com.box.sdkgen`)** + +```java +BoxOAuth auth = new BoxOAuth(new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET").build()); +String authorizationUrl = auth.getAuthorizeUrl(); +``` + +#### Authenticate + +The method for authenticating using the authorization code has been changed. With the `com.box.sdk` package of the SDK, +you had to provide the authorization code to the `BoxAPIConnection` class constructor. In the `com.box.sdkgen` package, +you need to call the `public AccessToken getTokensAuthorizationCodeGrant(String authorizationCode)` method of the `BoxOAuth` class. +The method now returns an AccessToken object with `accessToken` and `refreshToken` fields, +while the old one was creating a new instance of `BoxAPIConnection` class. + +**Old (`com.box.sdk`)** + +```java +BoxAPIConnection client = new BoxAPIConnection( + "[CLIENT_ID]", + "[CLIENT_SECRET]", + "[CODE]" +); +``` + +**New (`com.box.sdkgen`)** + +```java +auth.getTokensAuthorizationCodeGrant("AUTHORIZATION_CODE"); +BoxClient client = new BoxClient(auth); +``` + +### Store token and retrieve token callbacks + +In the `com.box.sdkgen` package you can define your own class delegated for storing and retrieving a token. It has to inherit from +`TokenStorage` and implement all of its abstract methods. Next step would be to pass an instance of this class to the +AuthConfig constructor. + +**New (`com.box.sdkgen`)** + +```java +TokenStorage customTokenStorage = new TokenStorage() { + @Override + public void store(AccessToken accessToken) { + // Store the access token + } + + @Override + public AccessToken get() { + // Retrieve the access token + return null; + } + + @Override + public void clear() { + // Clear the access token + } +}; + +OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET") + .tokenStorage(customTokenStorage) + .build(); +BoxOAuth auth = new BoxOAuth(config); +``` + +or reuse one of the provided implementations: `InMemoryTokenStorage`: + +```java +TokenStorage tokenStorage = new InMemoryTokenStorage(); +OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET") + .tokenStorage(tokenStorage) + .build(); +BoxOAuth auth = new BoxOAuth(config); +``` + +### Downscope token + +The process of downscoping token in the new version is similar to the old one. The main difference is that in the new version +you need to call `downscopeToken` method of the `BoxOAuth` class instead of `getLowerScopedToken` method of the `BoxAPIConnection` class. + +**Old (`com.box.sdk`)** + +```java +BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); + +String resource = "https://api.box.com/2.0/files/RESOURCE-ID"; +List scopes = new ArrayList(); +scopes.add("item_preview"); +scopes.add("item_content_upload"); + +ScopedToken token = api.getLowerScopedToken(scopes, resource); +``` + +**New (`com.box.sdkgen`)** + +```java +String resource = "https://api.box.com/2.0/files/123456789"; +List scopes = List.of("item_preview"); +AccessToken downscopedToken = auth.downscopeToken(scopes, resource, null, null); +BoxDeveloperTokenAuth downscopedAuth = new BoxDeveloperTokenAuth(downscopedToken.getAccessToken()); +BoxClient downscopedClient = new BoxClient(downscopedAuth); +``` + +### Revoke token + +To revoke current client's tokens in the `com.box.sdkgen` package, you need to call `revokeToken` method of the auth class instead of +`revoke` method. + +**Old (`com.box.sdk`)** + +```java +BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); +api.revokeToken(); +``` + +**New (`com.box.sdkgen`)** + +```java +client.auth.revokeToken() +``` + +## Configuration + +### As-User header + +The As-User header is used by enterprise admins to make API calls on behalf of their enterprise's users. +This requires the API request to pass an `As-User: USER-ID` header. The following examples assume that the client has +been instantiated with an access token with appropriate privileges to make As-User calls. + +In `com.box.sdk` package you could call client `asUser(String userID)` method to create a new client to impersonate the provided user. + +**Old (`com.box.sdk`)** + +```java +BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); +api.asUser("USER-ID"); +``` + +**New (`com.box.sdkgen`)** + +In the new version, the method was renamed to `withAsUserHeader` in the `BoxClient` class, +and returns a new instance of `BoxClient` class with the As-User header appended to all API calls made by the client. +The method accepts only user id as a parameter. + +```java +BoxClient userClient = client.withAsUserHeader("USER-ID"); +``` + +Additionally `BoxClient` offers a `withExtraHeaders(Map extraHeaders)` +method, which allows you to specify the custom set of headers, which will be included in every API call made by client. +Calling the `client.withExtraHeaders()` method creates a new client, leaving the original client unmodified. + +```java +BoxClient clientWithExtraHeaders = client.withExtraHeaders(new HashMap<>() {{ + put("X-My-Header", "124"); +}}); + +``` + +### Custom Base URLs + +**Old (`com.box.sdk`)** + +In `com.box.sdk` you could specify the custom base URLs, which will be used for API calls made by setting +the new values of static variables of the `API` class. + +```java +BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN"); +api.setBaseAppUrl("https://example.app.com"); +api.setBaseURL("https://example.com"); +api.setUploadURL("https://upload.example.com"); +api.setTokenURL("https://example.com/token"); +``` + +**New (`com.box.sdkgen`)** + +In `com.box.sdkgen` this functionality has been implemented as part of the `BoxClient` class. +By calling the `client.withCustomBaseUrls()` method, you can specify the custom base URLs that will be used for API +calls made by client. Following the immutability pattern, this call creates a new client, leaving the original client unmodified. + +```java +BaseUrls baseUrls = new BaseUrls.Builder() + .baseUrl("https://new-base-url.com") + .uploadUrl("https://my-company-upload-url.com") + .oauth2Url("https://my-company.com/oauth2") + .build(); +BoxClient clientWithCustomBaseUrl = client.withCustomBaseUrls(baseUrls); +``` + +## Convenience methods + +### Webhook validation + +Webhook validation is used to validate a webhook message by verifying the signature and the delivery timestamp. + +**Old (`com.box.sdk`)** + +In `com.box.sdk`, when you receive a webhook message from Box, to validate that it actually came from Box +you need to call `BoxWebHookSignatureVerifier#verify(String sigVersion, String sigAlgorithm, String primarySignature, String secondarySignature, String payload, String deliveryTimestamp)` method. +It would return a `boolean` value indicating whether the message was valid. + +```java +// Webhook message contents are shown for demonstration purposes +// Normally these would come from your HTTP handler + +// Webhook message HTTP body +String messagePayload = "{" ++ "\"type\":\"webhook_event"," ++ "\"webhook\":{" ++ "\"id\":\"1234567890\"" ++ "}," ++ "\"trigger\":\"FILE.UPLOADED\"," ++ "\"source\":{" ++ "\"id\":\"1234567890\"," ++ "\"type\":\"file\"," ++ "\"name\":\"Test.txt\"" ++ "}}"; + +// Webhook message HTTP headers +Map messageHeaders = new HashMap(); +headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f"); +headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00"); +headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256"); +headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI="); +headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo="); +headers.put("BOX-SIGNATURE-VERSION", "1"); + +// Your application's webhook keys, obtained from the Box Developer Console +String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip"; +String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL"; + +BoxWebHookSignatureVerifier verifier = new BoxWebHookSignatureVerifier(primaryKey, secondaryKey); +boolean isValidMessage = verifier.verify( + headers.get("BOX-SIGNATURE-VERSION"), + headers.get("BOX-SIGNATURE-ALGORITHM"), + headers.get("BOX-SIGNATURE-PRIMARY"), + headers.get("BOX-SIGNATURE-SECONDARY"), + messagePayload, + headers.get("BOX-DELIVERY-TIMESTAMP") +); +``` + +**New (`com.box.sdkgen`)** + +In the `com.box.sdkgen` package of ths SDK, the `WebhooksManager.validateMessage()` method requires the `messagePayload` to be of type `string`, +map of headers to be of type `Map`, and the primary and secondary keys to be of type `String`. + +```java +// Webhook message HTTP body +String messagePayload = "{" + + "\"type\":\"webhook_event"," + + "\"webhook\":{" + + "\"id\":\"1234567890\"" + + "}," + + "\"trigger\":\"FILE.UPLOADED\"," + + "\"source\":{" + + "\"id\":\"1234567890\"," + + "\"type\":\"file\"," + + "\"name\":\"Test.txt\"" + + "}}"; + +// Webhook message HTTP headers +Map messageHeaders = new HashMap(); +headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f"); +headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00"); +headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256"); +headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI="); +headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo="); +headers.put("BOX-SIGNATURE-VERSION", "1"); + +// Your application's webhook keys, obtained from the Box Developer Console +String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip"; +String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL"; + +boolean isValidMessage = WebhooksManager.validateMessage( + messagePayload, messageHeaders, primaryKey, secondaryKey); +) +``` + +### Chunked upload of big files + +For large files or in cases where the network connection is less reliable, you may want to upload the file in parts. +This allows a single part to fail without aborting the entire upload, and failed parts are being retried automatically. + +**Old (`com.box.sdk`)** + +In `com.box.sdk`, you could use the `uploadLargeFile` method of the `BoxFolder` class to upload a large file. +This method accepted a `FileInputStream` as the input stream and the file size as a parameter. The method also required + +```java +File myFile = new File("My Large_File.txt"); +FileInputStream stream = new FileInputStream(myFile); + +BoxFolder rootFolder = BoxFolder.getRootFolder(api); +BoxFile.Info fileInfo = rootFolder.uploadLargeFile(inputStream, "My_Large_File.txt", myFile.length()); +``` + +**New (`com.box.sdkgen`)** + +In `com.box.sdkgen`, the equivalent method is `chunked_uploads.uploadBigFile()`. It accepts a file-like object +as the `file` parameter, and the `fileName` and `fileSize` parameters are now passed as arguments. +The `parentFolderId` parameter is also required to specify the folder where the file will be uploaded. + +```java +InputStream file = new FileInputStream(myFile); +String fileName = "My_Large_File.txt"; +long fileSize = 1234556L; +String parentFolderId = "123456789"; + +File uploadedFile = client.getChunkedUploads().uploadBigFile(file, fileName, fileSize, parentFolderId); +``` diff --git a/migration-guides/from-v3-to-v4.md b/migration-guides/from-v3-to-v4.md new file mode 100644 index 000000000..5bcf2f164 --- /dev/null +++ b/migration-guides/from-v3-to-v4.md @@ -0,0 +1,243 @@ +# Migration guide for versions 3.x.x -> 4.x.x + + + + +- [Configuration changes](#configuration-changes) + - [BoxDeveloperEditionAPIConnection](#boxdevelopereditionapiconnection) + - [MaxRequestAttempts](#maxrequestattempts) +- [Removed deprecated methods and classes](#removed-deprecated-methods-and-classes) +- [Replaced methods and classes](#replaced-methods-and-classes) + - [Shared links](#shared-links) + - [Retention Policies](#retention-policies) + - [Enterprise Events](#enterprise-events) + - [Search](#search) + - [BoxGroup](#boxgroup) + - [MetadataTemplate](#metadatatemplate) + - [Others](#others) + + + +The most important change this release includes is the replacement of the HTTP library from a native one to +OkHttp which allows SDK to: + +- Support the HTTP2 version of the HTTP protocol. +- Support proxies that do not use only basic authentication method. For details on creating custom proxy authenticators and an example of + NTLM proxy authentication, see [here](https://github.com/box/box-java-sdk/blob/kb/ok-http/doc/configuration.md#custom-proxy-authenticator). + +# Configuration changes + +## BoxDeveloperEditionAPIConnection + +Replaced `com.box.sdk.BoxDeveloperEditionAPIConnection#getAppUserConnection`with `com.box.sdk.BoxDeveloperEditionAPIConnection#getUserConnection`. + +### Example + +To create `com.box.sdk.BoxDeveloperEditionAPIConnection` configured for user access: + +```java +Reader reader = new FileReader("some-config.json"); +BoxConfig boxConfig = BoxConfig.readFrom(reader); + +BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getUserConnection(boxConfig); +``` + +### Documentation + +You can read more on BoxDeveloperEditionAPIConnection [here](../../README.md#boxdevelopereditionapiconnectionasenterpriseuser). + +## MaxRequestAttempts + +The `MaxRequestAttempts` are removed from `com.box.sdk.BoxGlobalSettings` and replaced with `MaxRetryAttempts`. +However, if you have API connection stored with the deprecated `MaxRequestAttempts` value it will be restored into `MaxRetryAttempts`. + +# Removed deprecated methods and classes + +1. `com.box.sdk.BoxAPIRequest.BoxAPIRequest(java.net.URL, java.lang.String)` - use constuctor that accepts `com.box.sdk.BoxAPIConnection`. +2. `com.box.sdk.BoxUser.moveFolderToUser` - this method is removed as this operation is not allowed by API. You can only transfer root folder to another user using `com.box.sdk.BoxUser.transferContent`. + +# Replaced methods and classes + +## Getting thumbnail + +Method `com.box.sdk.BoxFile.getThumbnail` was removed. To get any file representation use `com.box.sdk.BoxFile.getRepresentationContent(java.lang.String, java.io.OutputStream)` +or `com.box.sdk.BoxFile.getRepresentationContent(java.lang.String, java.lang.String, java.io.OutputStream)`. + +### Example + +To read the PDF representation of file with id `12345`: + +```java +ByteArrayOutputStream output = new ByteArrayOutputStream(); + +BoxFile file = new BoxFile(api, "12345"); +file.getRepresentationContent("[pdf]", output); +``` + +### Documentation + +For more details on getting representation content go [here](../files.md#get-representation-content). + +## Shared links + +Removed variant of methods that do not use `com.box.sdk.sharedlink.BoxSharedLinkRequest`: + +1. `com.box.sdk.BoxItem.createSharedLink` +2. `com.box.sdk.BoxFile.createSharedLink` +3. `com.box.sdk.BoxFolder.createSharedLink` +4. `com.box.sdk.BoxWebLink.createSharedLink` + +### Example + +If you want to create a shared link, first create `com.box.sdk.sharedlink.BoxSharedLinkRequest`: + +```java +Date unsharedDate = ... +BoxFile file = new BoxFile(api, "id"); +BoxSharedLinkRequest sharedLinkRequest = new BoxSharedLinkRequest() + .access(OPEN) + .permissions(true, true) + .unsharedDate(unsharedDate); + +BoxSharedLink sharedLink = file.createSharedLink(sharedLinkRequest); +``` + +### Documentation + +For details on shared links, see: + +1. [Create shared link for file](../files.md#create-a-shared-link) +2. [Create shared link for folder](../folders.md#create-a-shared-link) +3. [Create shared link for web link](../weblinks.md#create-shared-link) + +## Retention Policies + +Removed variant of methods that were not using `com.box.sdk.BoxRetentionPolicy.BoxRetentionPolicyAction`: + +1. `com.box.sdk.BoxRetentionPolicy.createFinitePolicy` + +### Example + +If you want to create a finite retention policy: + +```java +BoxRetentionPolicy.createFinitePolicy(api, "My 30 days retention policy", 30, BoxRetentionPolicyAction.PermanentlyDelete); +``` + +### Documentation + +You can read more on creating retention policies [here](../retention_policies.md#create-retention-policy). + +## Enterprise Events + +Removed variant of methods that were not using `com.box.sdk.EnterpriseEventsRequest`: + +1. `com.box.sdk.EventLog.getEnterpriseEvents` + +### Example + +If you want to get historical enterprise events, first create `com.box.sdk.EnterpriseEventsRequest`: + +```java +EnterpriseEventsRequest request = new EnterpriseEventsRequest().limit(20); +EventLog.getEnterpriseEvents(api, request1); +// process recieved events +``` + +### Documentation + +You can read more on getting enterprise events [here](../events.md#enterprise--admin--events). + +## Search + +Method `com.box.sdk.BoxFolder.search` is replaced with class `com.box.sdk.BoxSearch`. + +### Example + +If you would like to find the first 10 files matching "taxes": + +```java +long offsetValue = 0; +long limitValue = 10; +BoxSearchParameters searchParams = new BoxSearchParameters(); +searchParams.setQuery("taxes"); +searchParams.setType("file"); + +BoxSearch boxSearch = new BoxSearch(api); +boxSearch.searchRange(offsetValue, limitValue, searchParams); +``` + +### Documentation + +You can read more on search [here](../search.md). + +## BoxGroup + +All methods that use `com.box.sdk.BoxGroupMembership.Role` were removed. Use ones that use `com.box.sdk.BoxGroupMembership.GroupRole`. +Also `com.box.sdk.BoxGroupMembership.Role` was replaced with `com.box.sdk.BoxGroupMembership.GroupRole`. + +### Example + +To add a new member to a group with specific role: + +```java +BoxUser user = ... +BoxGroup boxGroup = new BoxGroup(api, "group_id"); +boxGroup.addMembership(user, BoxGroupMembership.GroupRole.ADMIN); +``` + +To get membership role use `com.box.sdk.BoxGroupMembership.Info.getGroupRole`: + +```java +BoxGroupMembership membership = new BoxGroupMembership(api, "membership_id"); +membership.getInfo().getGroupRole(); +``` + +To change membership role use `com.box.sdk.BoxGroupMembership.Info.setGroupRole`: + +```java +BoxGroupMembership membership = new BoxGroupMembership(api, "membership_id"); +BoxGroupMembership.Info membershipInfo = membership.getInfo(); +membershipInfo.setGroupRole(BoxGroupMembership.GroupRole.MEMBER); +membership.updateInfo(membershipInfo); +``` + +### Documentation + +You can read more on groups [here](../groups.md). + +## MetadataTemplate + +In `com.box.sdk.MetadataTemplate` methods that do not use `com.box.sdk.MetadataQuery` were removed. + +### Example + +To execute a metadata query first create `com.box.sdk.MetadataQuery` instance. + +```java +MetadataQuery mQuery = new MetadataQuery("enterprise_341532.test"); +mQuery.setQuery("testfield = :arg"); +mQuery.setAncestorFolderId("0"); +mQuery.setOrderBy( + MetadataQuery.OrderBy.ascending("primarySortKey"), + MetadataQuery.OrderBy.ascending("secondarySortKey") +); +mQuery.addParameter("arg", "test"); +mQuery.setFields("metadata.enterprise_341532.test.customField"); +MetadataTemplate.executeMetadataQuery(api, mQuery); +``` + +### Documentation + +You can read more on how to execute metadata query [here](../metadata_template.md#execute-metadata-query). + +## Others + +| Old | New | +| :---------------------------------------------------- | :-------------------------------------------------- | +| `com.box.sdk.BoxEvent.getType` | `com.box.sdk.BoxEvent.getEventType` | +| `com.box.sdk.BoxEvent.Type` | `com.box.sdk.BoxEvent.EventType` | +| `com.box.sdk.BoxFile.uploadVersion` | `com.box.sdk.BoxFile.uploadNewVersion` | +| `com.box.sdk.BoxGlobalSettings.getMaxRequestAttempts` | `com.box.sdk.BoxGlobalSettings.getMaxRetryAttempts` | +| `com.box.sdk.BoxGlobalSettings.setMaxRequestAttempts` | `com.box.sdk.BoxGlobalSettings.setMaxRetryAttempts` | +| `com.box.sdk.BoxTask.Info.getAction` | `com.box.sdk.BoxTask.Info.getTaskType` | diff --git a/migration-guides/from-v4-to-v10.md b/migration-guides/from-v4-to-v10.md index a38d4f5de..23c3773b5 100644 --- a/migration-guides/from-v4-to-v10.md +++ b/migration-guides/from-v4-to-v10.md @@ -7,32 +7,8 @@ - [Installation](#installation) - [Maven](#maven) - [Gradle](#gradle) -- [Key differences](#key-differences) - - [Manager approach](#manager-approach) - - [Immutable design](#immutable-design) - - [Consistent method signature](#consistent-method-signature) -- [Authentication](#authentication) - - [Developer Token](#developer-token) - - [JWT Auth](#jwt-auth) - - [Using JWT configuration file](#using-jwt-configuration-file) - - [Providing JWT configuration manually](#providing-jwt-configuration-manually) - - [Authenticate user](#authenticate-user) - - [Client Credentials Grant](#client-credentials-grant) - - [Obtaining Service Account token](#obtaining-service-account-token) - - [Obtaining User token](#obtaining-user-token) - - [Switching between Service Account and User](#switching-between-service-account-and-user) - - [OAuth 2.0 Auth](#oauth-20-auth) - - [Get Authorization URL](#get-authorization-url) - - [Authenticate](#authenticate) - - [Store token and retrieve token callbacks](#store-token-and-retrieve-token-callbacks) - - [Downscope token](#downscope-token) - - [Revoke token](#revoke-token) -- [Configuration](#configuration) - - [As-User header](#as-user-header) - - [Custom Base URLs](#custom-base-urls) -- [Convenience methods](#convenience-methods) - - [Webhook validation](#webhook-validation) - - [Chunked upload of big files](#chunked-upload-of-big-files) +- [Supported Environments](#supported-environments) +- [Highlighting the Key Differences](#highlighting-the-key-differences) @@ -44,19 +20,19 @@ based on Open API Specification. This means you can leverage the most up-to-date applications without delay. We introduced this major version bump to reflect the significant codebase changes and to align with other Box SDKs, which will also adopt generated code starting from their v10 releases. More information and benefits of using the new can be found in the -[README](https://github.com/box/box-java-sdk/blob/sdk-gen/README.md) file. +[README](../README.md) file. ## Installation To install v10 version of Box Java SDK, you can use Maven or Gradle. The library is available in the [Maven Central Repository](https://search.maven.org/artifact/com.box/box-java-sdk). -Soon we are going to introduce v5 version of Box Java SDK that will combine package `com.box.sdk` from -v4 and `com.box.sdkgen` from v10 of the SDK so that code from both versions could be used in the same project. +We have also introduced v5 version of Box Java SDK that consolidates both the manually maintained +`com.box.sdk` package from v4 and the new, auto-generated `com.box.sdkgen` package from v10. If you would like to use a feature available only in the new SDK, you won't need to necessarily migrate all your code to use generated SDK at once. You will be able to use a new feature from the `com.box.sdkgen` package, -while keeping the rest of your code unchanged. Note that it may be required to use fully qualified class names -to avoid conflicts between two packages. However, we recommend to fully migrate to the v10 of the SDK eventually. +while keeping the rest of your code unchanged. However, we recommend to fully migrate to the v10 of the SDK eventually. +More information about v4 version can be found in the [migration guide from v4 to v5](./from-v4-to-v5.md). ### Maven @@ -73,619 +49,19 @@ in `pom.xml`to 10.0.0 or higher: ### Gradle -To bump a dependency in your Gradle project, bump the version useed in your `build.gradle` file: +To bump a dependency in your Gradle project, bump the version used in your `build.gradle` file: ```groovy implementation 'com.box:box-java-sdk:10.0.0' ``` -## Key differences +## Supported Environments -### Manager approach +Both v4 and v10 of the Box Java SDK share the same Java version requirement: Java 8 or higher. +No changes to your environment are needed when upgrading from v4 to v10. -The main difference between the manual v4 version of the SDK and the nextgen generated one, -is the way how API methods are aggregated into objects. +## Highlighting the Key Differences -**Old (`v4`)** - -Firstly, in the v4 version of the SDK to be able to perform any action on an API object, e.g. `User`, you first had to create its class. -To do it is required to call: - -```java -BoxUser user = new BoxUser(api, "12345"); -``` - -to create a class representing an already existing User with id '12345', or create a new one with a call: - -```java -BoxUser.Info createdUserInfo = BoxUser.createAppUser(api, "A User"); -BoxUser user = new BoxUser(api, createdUserInfo.getID()); -``` - -Then, you could perform any action on created class, which will affect the user, e.g. - -```java -BoxUser.Info info = user.new Info(); -info.setName(name); -user.updateInfo(info); -``` - -**New (`v10`)** - -In the v10 version of the SDK the API methods are grouped into dedicated manager classes, e.g. `User` object -has dedicated `UserManager` class. Each manager class instance is available in `BoxClient` object. -The fields storing references to the managers are named in the plural form of the resource that the -manager handles - `client.users` for `UsersManager`. If you want to perform any operation -connected with a `User` you need to call a respective method of `UserManager`. -For example, to get info about existing user you need to call: - -```java -UserFull user = client.users.getUsersById("12345"); -``` - -or to create a new user: - -```java -CreateUserRequestBody requestBody = - new CreateUserRequestBody.Builder("John Doe").build(); -UserFull user = client.users.createUser(requestBody); -``` - -The `UserFull` object returned by both of these methods is a data class - it does not contain any methods to call. -To perform any action on `User` object, you need to still use a `UserManager` method for that. -Usually these methods have a first argument, which accepts id of the object you want to access, -e.g. to update a user name, call method: - -```java -UpdateUserByIdRequestBody requestBody = - new UpdateUserByIdRequestBody.Builder().name("Mary").build(); -UserFull updatedUser = client.users.updateUserById(user.getId(), requestBody); -``` - -### Immutable design - -The v10 is designed to be mostly immutable. This means that methods, -which used to modify the existing object in v4 release now return a new instance of the class with the modified state. -This design pattern is used to avoid side effects and make the code more predictable and easier to reason about. -Methods, which returns a new modified instance of an object, will always have a prefix `with` in their names, e.g. - -**New (`v10`)** - -```java -BoxClient client = new BoxClient(auth); -BoxClient asUserClient = client.withAsUserHeader("USER_ID"); -``` - -### Consistent method signature - -To facilitate easier work with the new SDK, we have changed the API method signatures to be consistent and unified. - -**Old (`v4`)** - -In the manual version, API methods had numerous parameters, which were not grouped into any objects and were passed as separate arguments, e.g. the method for creating a sign request looked like this: - -```java -public static BoxSignRequest.Info createSignRequest(BoxAPIConnection api, List sourceFiles, - List signers, String parentFolderId, - BoxSignRequestCreateParams optionalParams) -``` - -**New (`v10`)** - -In the v10, we have adopted an approach of aggregating parameters into types based on their nature (path, body, query, headers). -This can be seen in the example corresponding to the above: - -```java -public SignRequest createSignRequest( - SignRequestCreateRequest requestBody, CreateSignRequestHeaders headers) -``` - -According to the convention, if an API endpoint requires a parameter placed in the URL path, it will appear at the beginning of our method, such as `fileId` in this case. When a request allows for a body, as in `POST` or `PUT`, the method includes a parameter named `requestBody`. Following that, the method signature may include the `queryParams` parameter, followed by `headers`. - -The types of parameters `requestBody`, `queryParams`, and `headers` are specific to each endpoint and, in their definition, encompass all fields allowed by the API. - -It's worth noting here that when all fields of a particular type are optional, the entire parameter becomes optional as well. This allows us to pass only the parameters we actually want to provide when calling a given method, without the risk of not providing a sufficient number of parameters. - -## Authentication - -The v10 release of Box Java SDK library offers the same authentication methods as the v4 one. -Let's see the differences of their usage: - -### Developer Token - -**Old (`v4`)** - -```java -BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN"); -``` - -The v10 release provides a convenient `BoxDeveloperTokenAuth`, which allows authenticating -using developer token without necessity to provide a Client ID and Client Secret - -**New (`v10`)** - -```java -BoxDeveloperTokenAuth auth = new BoxDeveloperTokenAuth("YOUR-DEVELOPER-TOKEN"); -BoxClient client = new BoxClient(auth); -``` - -### JWT Auth - -#### Using JWT configuration file - -**Old (`v4`)** - -The static method, which reads the JWT configuration file has been changed: - -```java -Reader reader = new FileReader("src/example/config/config.json"); -BoxConfig boxConfig = BoxConfig.readFrom(reader); -IAccessTokenCache tokenCache = new InMemoryLRUAccessTokenCache(100); -BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig, tokenCache); -``` - -**New (`v10`)** - -```java -TokenStorage tokenStorage = new InMemoryTokenStorage(); // or any other implementation of TokenStorage -JWTConfig config = JWTConfig.fromConfigFile("src/example/config/config.json", tokenStorage); -BoxJWTAuth auth = new BoxJWTAuth(config); -BoxClient client = new BoxClient(auth); -``` - -#### Providing JWT configuration manually - -Some params in `JWTConfig` constructor have slightly different names than one in old `JWTAuth` class. - -**Old (`v4`)** - -```java -JWTEncryptionPreferences jwtPreferences = new JWTEncryptionPreferences(); -jwtPreferences.setPublicKeyID("PUBLIC-KEY-ID"); -jwtPreferences.setPrivateKeyPassword("PRIVATE-KEY-PASSWORD"); -jwtPreferences.setPrivateKey("PRIVATE-KEY"); -jwtPreferences.setEncryptionAlgorithm(EncryptionAlgorithm.RSA_SHA_256); - -IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(100); -BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection - .getUserConnection("USER-ID", "CLIENT-ID","CLIENT-SECRET", jwtPreferences, accessTokenCache); - -BoxUser.Info userInfo = BoxUser.getCurrentUser(api).getInfo(); -``` - -**New (`v10`)** - -```java -TokenStorage tokenStorage = new InMemoryTokenStorage(); -JWTConfig config = new JWTConfig.Builder("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "JWT_KEY_ID", "PRIVATE_KEY", "PRIVATE_KEY_PASSWORD") - .enterpriseId("123456") - .tokenStorage(tokenStorage) - .build(); -BoxJWTAuth auth = new BoxJWTAuth(config); -BoxClient client = new BoxClient(auth); -``` - -#### Authenticate user - -In v4 release method for user authentication was named `BoxDeveloperEditionAPIConnection getUserConnection(String userId, BoxConfig boxConfig, IAccessTokenCache accessTokenCache)` -and was accepting user id. The method was returning a new instance of `BoxDeveloperEditionAPIConnection` class, which was exchanging the existing token with the one with the user access. - -**Old (`v4`)** - -```java -BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getUserConnection("USER_ID", boxConfig, tokenCache); -``` - -**New (`v10`)** - -In v10, to authenticate as user you need to call -`public BoxJWTAuth withUserSubject(String userId, TokenStorage tokenStorage)` method with id of the user -to authenticate. The method returns a new instance of `BoxJWTAuth` class, which will perform authentication call -in scope of the user on the first API call. The `tokenStorage` parameter is optional and allows to provide a custom -token storage for the new instance of `BoxJWTAuth` class. The new auth instance can be used to create a new user client -instance. - -```java -BoxJWTAuth userAuth = auth.withUserSubject("USER_ID"); -BoxClient userClient = new BoxClient(userAuth); -``` - -### Client Credentials Grant - -#### Obtaining Service Account token - -To authenticate as enterprise, the only difference between the v4 and v10 is using the `CCGConfig` as a middle step. - -**Old (`v4`)** - -```java -BoxCCGAPIConnection api = BoxCCGAPIConnection.applicationServiceAccountConnection( - "client_id", - "client_secret", - "enterprise_id" -); -``` - -**New (`v10`)** - -```java -CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET") - .enterpriseId("ENTERPRISE_ID") - .build(); -BoxCCGAuth auth = new BoxCCGAuth(config); -BoxClient client = new BoxClient(auth); -``` - -#### Obtaining User token - -To authenticate as user, the only difference between the versions is using the `CCGConfig` as a middle step. - -**Old (`v4`)** - -```java -BoxCCGAPIConnection api = BoxCCGAPIConnection.userConnection( - "client_id", - "client_secret", - "user_id" -); -``` - -**New (`v10`)** - -```java -CCGConfig config = new CCGConfig.Builder("YOUR_CLIENT", "YOUR_CLIENT_SECRET") - .userId("USER_ID") - .build(); -BoxCCGAuth auth = new BoxCCGAuth(config); -BoxClient client = new BoxClient(auth); -``` - -### Switching between Service Account and User - -In v4 release, if you want to switch between the Service Account and User, you need to create another API connection. - -In the v10, to keep the immutability design, the methods switching authenticated subject were replaced with methods -returning a new instance of `BoxCCGAuth` class. The new instance will fetch a new token on the next API call. -The new auth instance can be used to create a new client instance. You can also specify `tokenStorage` parameter -to provide a custom token storage for the new instance. -The old instance of `BoxCCGAuth` class will remain unchanged and will still use the old token. - -**New (`v10`)** - -```java -BoxCCGAuth userAuth = auth.withUserSubject("USER_ID"); -BoxClient userClient = new BoxClient(userAuth); -``` - -```java -BoxCCGAuth entAuth = auth.withEnterpriseSubject("ENTERPRISE_ID"); -BoxClient entClient = new BoxClient(entAuth); -``` - -### OAuth 2.0 Auth - -#### Get Authorization URL - -To get authorization url in the v10 release, you need to first create the `BoxOAuth` class using -`OAuthConfig` class. Then to get authorization url, call -`public String getAuthorizeUrl(GetAuthorizeUrlOptions options)`. Note that this method accepts the instance of `GetAuthorizeUrlOptions` class, which allows specifying extra options to API call. - -**Old (`v4`)** - -In the v4, we did not have any method to get the authorization URL. Instead, we had to manually create the URL. - -```java -String authorizationUrl = "https://account.box.com/api/oauth2/authorize?client_id=[CLIENT_ID]&response_type=code"; -``` - -**New (`v10`)** - -```java -BoxOAuth auth = new BoxOAuth(new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET").build()); -String authorizationUrl = auth.getAuthorizeUrl(); -``` - -#### Authenticate - -The method for authenticating using the authorization code has been changed. With the v4 version of the SDK, -you had to provide the authorization code to the `BoxAPIConnection` class constructor. In the v10 version, -you need to call the `public AccessToken getTokensAuthorizationCodeGrant(String authorizationCode)` method of the `BoxOAuth` class. -The method now returns an AccessToken object with `accessToken` and `refreshToken` fields, -while the old one was creating a new instance of `BoxAPIConnection` class. - -**Old (`v4`)** - -```java -BoxAPIConnection client = new BoxAPIConnection( - "[CLIENT_ID]", - "[CLIENT_SECRET]", - "[CODE]" -); -``` - -**New (`v10`)** - -```java -auth.getTokensAuthorizationCodeGrant("AUTHORIZATION_CODE"); -BoxClient client = new BoxClient(auth); -``` - -### Store token and retrieve token callbacks - -In the v10 release you can define your own class delegated for storing and retrieving a token. It has to inherit from -`TokenStorage` and implement all of its abstract methods. Next step would be to pass an instance of this class to the -AuthConfig constructor. - -**New (`v10`)** - -```java -TokenStorage customTokenStorage = new TokenStorage() { - @Override - public void store(AccessToken accessToken) { - // Store the access token - } - - @Override - public AccessToken get() { - // Retrieve the access token - return null; - } - - @Override - public void clear() { - // Clear the access token - } -}; - -OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET") - .tokenStorage(customTokenStorage) - .build(); -BoxOAuth auth = new BoxOAuth(config); -``` - -or reuse one of the provided implementations: `InMemoryTokenStorage`: - -```java -TokenStorage tokenStorage = new InMemoryTokenStorage(); -OAuthConfig config = new OAuthConfig.Builder("CLIENT_ID", "CLIENT_SECRET") - .tokenStorage(tokenStorage) - .build(); -BoxOAuth auth = new BoxOAuth(config); -``` - -### Downscope token - -The process of downscoping token in the new version is similar to the old one. The main difference is that in the new version -you need to call `downscopeToken` method of the `BoxOAuth` class instead of `getLowerScopedToken` method of the `BoxAPIConnection` class. - -**Old (`v4`)** - -```java -BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); - -String resource = "https://api.box.com/2.0/files/RESOURCE-ID"; -List scopes = new ArrayList(); -scopes.add("item_preview"); -scopes.add("item_content_upload"); - -ScopedToken token = api.getLowerScopedToken(scopes, resource); -``` - -**New (`v10`)** - -```java -String resource = "https://api.box.com/2.0/files/123456789"; -List scopes = List.of("item_preview"); -AccessToken downscopedToken = auth.downscopeToken(scopes, resource, null, null); -BoxDeveloperTokenAuth downscopedAuth = new BoxDeveloperTokenAuth(downscopedToken.getAccessToken()); -BoxClient downscopedClient = new BoxClient(downscopedAuth); -``` - -### Revoke token - -To revoke current client's tokens in the v10 release, you need to call `revokeToken` method of the auth class instead of -`revoke` method. - -**Old (`v4`)** - -```java -BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); -api.revokeToken(); -``` - -**New (`v10`)** - -```java -client.auth.revokeToken() -``` - -## Configuration - -### As-User header - -The As-User header is used by enterprise admins to make API calls on behalf of their enterprise's users. -This requires the API request to pass an `As-User: USER-ID` header. The following examples assume that the client has -been instantiated with an access token with appropriate privileges to make As-User calls. - -In v4 release you could call client `asUser(String userID)` method to create a new client to impersonate the provided user. - -**Old (`v4`)** - -```java -BoxAPIConnection api = new BoxAPIConnection("YOUR-ACCESS-TOKEN"); -api.asUser("USER-ID"); -``` - -**New (`v10`)** - -In the new version, the method was renamed to `withAsUserHeader` in the `BoxClient` class, -and returns a new instance of `BoxClient` class with the As-User header appended to all API calls made by the client. -The method accepts only user id as a parameter. - -```java -BoxClient userClient = client.withAsUserHeader("USER-ID"); -``` - -Additionally `BoxClient` offers a `withExtraHeaders(Map extraHeaders)` -method, which allows you to specify the custom set of headers, which will be included in every API call made by client. -Calling the `client.withExtraHeaders()` method creates a new client, leaving the original client unmodified. - -```java -BoxClient clientWithExtraHeaders = client.withExtraHeaders(new HashMap<>() {{ - put("X-My-Header", "124"); -}}); - -``` - -### Custom Base URLs - -**Old (`v4`)** - -In v4 you could specify the custom base URLs, which will be used for API calls made by setting -the new values of static variables of the `API` class. - -```java -BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN"); -api.setBaseAppUrl("https://example.app.com"); -api.setBaseURL("https://example.com"); -api.setUploadURL("https://upload.example.com"); -api.setTokenURL("https://example.com/token"); -``` - -**New (`v10`)** - -Inv10 this functionality has been implemented as part of the `BoxClient` class. -By calling the `client.withCustomBaseUrls()` method, you can specify the custom base URLs that will be used for API -calls made by client. Following the immutability pattern, this call creates a new client, leaving the original client unmodified. - -```java -BaseUrls baseUrls = new BaseUrls.Builder() - .baseUrl("https://new-base-url.com") - .uploadUrl("https://my-company-upload-url.com") - .oauth2Url("https://my-company.com/oauth2") - .build(); -BoxClient clientWithCustomBaseUrl = client.withCustomBaseUrls(baseUrls); -``` - -## Convenience methods - -### Webhook validation - -Webhook validation is used to validate a webhook message by verifying the signature and the delivery timestamp. - -**Old (`v4`)** - -In v4, when you receive a webhook message from Box, to validate that it actually came from Box -you need to call `BoxWebHookSignatureVerifier#verify(String sigVersion, String sigAlgorithm, String primarySignature, String secondarySignature, String payload, String deliveryTimestamp)` method. -It would return a `boolean` value indicating whether the message was valid. - -```java -// Webhook message contents are shown for demonstration purposes -// Normally these would come from your HTTP handler - -// Webhook message HTTP body -String messagePayload = "{" -+ "\"type\":\"webhook_event"," -+ "\"webhook\":{" -+ "\"id\":\"1234567890\"" -+ "}," -+ "\"trigger\":\"FILE.UPLOADED\"," -+ "\"source\":{" -+ "\"id\":\"1234567890\"," -+ "\"type\":\"file\"," -+ "\"name\":\"Test.txt\"" -+ "}}"; - -// Webhook message HTTP headers -Map messageHeaders = new HashMap(); -headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f"); -headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00"); -headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256"); -headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI="); -headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo="); -headers.put("BOX-SIGNATURE-VERSION", "1"); - -// Your application's webhook keys, obtained from the Box Developer Console -String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip"; -String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL"; - -BoxWebHookSignatureVerifier verifier = new BoxWebHookSignatureVerifier(primaryKey, secondaryKey); -boolean isValidMessage = verifier.verify( - headers.get("BOX-SIGNATURE-VERSION"), - headers.get("BOX-SIGNATURE-ALGORITHM"), - headers.get("BOX-SIGNATURE-PRIMARY"), - headers.get("BOX-SIGNATURE-SECONDARY"), - messagePayload, - headers.get("BOX-DELIVERY-TIMESTAMP") -); -``` - -**New (`v10`)** - -In the v10 version of ths SDK, the `WebhooksManager.validateMessage()` method requires the `messagePayload` to be of type `string`, -map of headers to be of type `Map`, and the primary and secondary keys to be of type `String`. - -```java -// Webhook message HTTP body -String messagePayload = "{" - + "\"type\":\"webhook_event"," - + "\"webhook\":{" - + "\"id\":\"1234567890\"" - + "}," - + "\"trigger\":\"FILE.UPLOADED\"," - + "\"source\":{" - + "\"id\":\"1234567890\"," - + "\"type\":\"file\"," - + "\"name\":\"Test.txt\"" - + "}}"; - -// Webhook message HTTP headers -Map messageHeaders = new HashMap(); -headers.put("BOX-DELIVERY-ID", "f96bb54b-ee16-4fc5-aa65-8c2d9e5b546f"); -headers.put("BOX-DELIVERY-TIMESTAMP", "2020-01-01T00:00:00-07:00"); -headers.put("BOX-SIGNATURE-ALGORITHM", "HmacSHA256"); -headers.put("BOX-SIGNATURE-PRIMARY", "6TfeAW3A1PASkgboxxA5yqHNKOwFyMWuEXny/FPD5hI="); -headers.put("BOX-SIGNATURE-SECONDARY", "v+1CD1Jdo3muIcbpv5lxxgPglOqMfsNHPV899xWYydo="); -headers.put("BOX-SIGNATURE-VERSION", "1"); - -// Your application's webhook keys, obtained from the Box Developer Console -String primaryKey = "4py2I9eSFb0ezXH5iPeQRcFK1LRLCdip"; -String secondaryKey = "Aq5EEEjAu4ssbz8n9UMu7EerI0LKj2TL"; - -boolean isValidMessage = WebhooksManager.validateMessage( - messagePayload, messageHeaders, primaryKey, secondaryKey); -) -``` - -### Chunked upload of big files - -For large files or in cases where the network connection is less reliable, you may want to upload the file in parts. -This allows a single part to fail without aborting the entire upload, and failed parts are being retried automatically. - -**Old (`v4`)** - -In the v4, you could use the `uploadLargeFile` method of the `BoxFolder` class to upload a large file. -This method accepted a `FileInputStream` as the input stream and the file size as a parameter. The method also required - -```java -File myFile = new File("My Large_File.txt"); -FileInputStream stream = new FileInputStream(myFile); - -BoxFolder rootFolder = BoxFolder.getRootFolder(api); -BoxFile.Info fileInfo = rootFolder.uploadLargeFile(inputStream, "My_Large_File.txt", myFile.length()); -``` - -**New (`v10`)** - -In the v10, the equivalent method is `chunked_uploads.uploadBigFile()`. It accepts a file-like object -as the `file` parameter, and the `fileName` and `fileSize` parameters are now passed as arguments. -The `parentFolderId` parameter is also required to specify the folder where the file will be uploaded. - -```java -InputStream file = new FileInputStream(myFile); -String fileName = "My_Large_File.txt"; -long fileSize = 1234556L; -String parentFolderId = "123456789"; - -File uploadedFile = client.getChunkedUploads().uploadBigFile(file, fileName, fileSize, parentFolderId); -``` +There are important differences between the `com.box.sdk` (v4) and the generated `com.box.sdkgen` (v10) packages. +We have prepared a separate document that presents the main differences and provides guidance to help you migrate. +For side-by-side code examples, see: [Migration guide: migrate from `com.box.sdk` to `com.box.sdkgen` package](./from-com-box-sdk-to-com-box-sdkgen.md). diff --git a/migration-guides/from-v4-to-v5.md b/migration-guides/from-v4-to-v5.md new file mode 100644 index 000000000..ce7e0e127 --- /dev/null +++ b/migration-guides/from-v4-to-v5.md @@ -0,0 +1,109 @@ +# Migration guide from v4 to v5 version of `box-java-sdk` + + + + +- [Introduction](#introduction) +- [Installation](#installation) + - [Maven](#maven) + - [Gradle](#gradle) +- [Supported Environments](#supported-environments) +- [Highlighting the Key Differences](#highlighting-the-key-differences) + - [Using the Box Java SDK v5](#using-the-box-java-sdk-v5) + + + +## Introduction + +The v5 release of the Box Java SDK is a transitional version designed to help developers migrate from +the manually maintained v4 SDK to the modern, auto-generated v10+ SDK. + +This release combines two packages into a single artifact: + +- `com.box.sdk` - the manually maintained package from v4. +- `com.box.sdkgen` - the new, auto-generated module built from the official OpenAPI specification (and the sole component of the v10 SDK). + +This hybrid approach allows you to gradually adopt the new `com.box.sdkgen` features +while continuing to use your existing v4 integration, eliminating the need for an immediate full rewrite. + +## Installation + +To install v5 version of Box Java SDK, you can use Maven or Gradle. The library is available in the +[Maven Central Repository](https://search.maven.org/artifact/com.box/box-java-sdk). + +### Maven + +To upgrade from v4 to v5, in you Maven project just bump the version of the Box Java SDK library +in `pom.xml`to 5.0.0 or higher: + +```xml + + com.box + box-java-sdk + 5.0.0 + +``` + +### Gradle + +To upgrade from v4 to v5 of the Box Java SDK, simply update the library version in your Maven project’s `pom.xml` file +to 5.0.0 or higher: + +```groovy +implementation 'com.box:box-java-sdk:5.0.0' +``` + +## Supported Environments + +Both v4 and v5 of the Box Java SDK share the same Java version requirement: Java 8 or higher. +No changes to your environment are needed when upgrading from v4 to v5. + +## Highlighting the Key Differences + +The `com.box.sdk` package usage in v5 remains the same as in v4 and is not covered in this document. +If you are migrating code from `com.box.sdk` to `com.box.sdkgen`, which we recommend, +the key differences between the packages are documented in: + +- [Migration guide: com.box.sdk → com.box.sdkgen](./from-com-box-sdk-to-com-box-sdkgen.md) + +### Using the Box Java SDK v5 + +After migration to Box Java SDK v5, you can use both the manual Box Java SDK package `com.box.sdk` and the generated one `com.box.sdkgen`. +You just need to import the required classes from the appropriate package depending on which SDK you intend to use. +If both packages contain classes with the same name, you can use fully qualified names to resolve any naming conflicts. + +```java +import com.box.sdk.BoxConfig; +import com.box.sdk.BoxDeveloperEditionAPIConnection; + +import com.box.sdk.BoxFolder; +import com.box.sdkgen.box.jwtauth.BoxJWTAuth; +import com.box.sdkgen.box.jwtauth.JWTConfig; +import com.box.sdkgen.client.BoxClient; +import com.box.sdkgen.managers.folders.UpdateFolderByIdRequestBody; +import com.box.sdkgen.schemas.folder.Folder; + +import java.io.FileReader; +import java.io.Reader; + +public class Main { + public static void main(String[] args) throws Exception { + + Reader reader = new FileReader("src/example/config/config.json"); + BoxConfig boxConfig = BoxConfig.readFrom(reader); + BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(boxConfig); + + JWTConfig config = JWTConfig.fromConfigFile("src/example/config/config.json"); + BoxJWTAuth auth = new BoxJWTAuth(config); + BoxClient client = new BoxClient(auth); + + BoxFolder rootFolder = new BoxFolder(api, "0"); + BoxFolder.Info subfolder = rootFolder.createFolder("My Subfolder"); + Folder updatedFolder = client.getFolders().updateFolderById( + subfolder.getID(), + new UpdateFolderByIdRequestBody.Builder().name("My Updated Subfolder").build() + ); + System.out.println("Created folder with ID " + subfolder.getID() + " has been updated to " + updatedFolder.getName()); + } +} +``` diff --git a/migration-guides/from-v5-to-v10.md b/migration-guides/from-v5-to-v10.md new file mode 100644 index 000000000..91210c8dd --- /dev/null +++ b/migration-guides/from-v5-to-v10.md @@ -0,0 +1,61 @@ +# Migration guide from v5 to v10 version of `box-java-sdk` + + + + +- [Introduction](#introduction) +- [Installation](#installation) + - [Maven](#maven) + - [Gradle](#gradle) +- [Supported Environments](#supported-environments) +- [Migration Scope and Module Compatibility](#migration-scope-and-module-compatibility) + + + +## Introduction + +Version 10 of the Box Java SDK is a modern, fully auto-generated SDK built entirely from the `com.box.sdkgen` package. +In version 5, the SDK included two packages side by side: the manually maintained `com.box.sdk` and the generated `com.box.sdkgen`. +Starting with version 10, the `com.box.sdk` package has been removed, and only the `com.box.sdkgen` package remains. + +If you are migrating code from `com.box.sdk` to `com.box.sdkgen` package, detailed instructions are available in the dedicated +[Migration guide: migrate from `com.box.sdk` to `com.box.sdkgen` package](./from-com-box-sdk-to-com-box-sdkgen.md). + +## Installation + +To install v10 version of Box Java SDK, you can use Maven or Gradle. The library is available in the +[Maven Central Repository](https://search.maven.org/artifact/com.box/box-java-sdk). + +### Maven + +To start using generated version of the SDK in you Maven project just bump the version of the Box Java SDK library +in `pom.xml`to 10.0.0 or higher: + +```xml + + com.box + box-java-sdk + 10.0.0 + +``` + +### Gradle + +To bump a dependency in your Gradle project, bump the version used in your `build.gradle` file: + +```groovy +implementation 'com.box:box-java-sdk:10.0.0' +``` + +## Supported Environments + +Both v5 and v10 of the Box Java SDK share the same Java version requirement: Java 8 or higher. +No changes to your environment are needed when upgrading from v5 to v10. + +## Migration Scope and Module Compatibility + +If your project only uses the `com.box.sdkgen` package from v5, no code changes are required to migrate to v10. +The generated `com.box.sdkgen` package is the same in both v5 and v10. + +If your project still includes code that uses the legacy `com.box.sdk` module, follow the dedicated guide to update it: +[Migration guide: migrate from `com.box.sdk` to `com.box.sdkgen` package](./from-com-box-sdk-to-com-box-sdkgen.md).