Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
jdk: ['8', '11', '17']
jdk: ['11', '17']

steps:
- uses: actions/checkout@v4
Expand Down
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ The v4 SDK provides a modern, immutable client with enhanced type safety and imp
#### Gradle (Kotlin DSL)
```kotlin
dependencies {
implementation("com.chargebee:chargebee-java:4.0.0")
implementation("com.chargebee:chargebee-java:4.0.0-beta.3")
}
```

Expand All @@ -56,7 +56,7 @@ dependencies {
<dependency>
<groupId>com.chargebee</groupId>
<artifactId>chargebee-java</artifactId>
<version>4.0.0</version>
<version>4.0.0-beta.3</version>
</dependency>
```

Expand Down Expand Up @@ -221,23 +221,29 @@ The library provides a comprehensive exception hierarchy with **strongly-typed e

#### Exception Hierarchy

All Chargebee exceptions extend from `TransportException`, which is a checked exception:
All Chargebee exceptions extend from `ChargebeeException`, which is an unchecked exception:

```
TransportException (checked)
└── HttpException (HTTP status code errors: 4xx, 5xx)
├── ClientErrorException (4xx errors)
├── ServerErrorException (5xx errors)
└── APIException (Chargebee API errors)
├── InvalidRequestException (validation errors)
├── PaymentException (payment-related errors)
├── OperationFailedException (business logic errors)
├── BatchAPIException (batch operation errors)
└── UbbBatchIngestionInvalidRequestException (batch ingestion errors)
ChargebeeException (unchecked - extends RuntimeException)
├── ConfigurationException (setup/config errors)
└── TransportException (runtime API errors)
├── NetworkException (DNS failures, connection refused)
├── TimeoutException (connect/read timeouts)
└── HttpException (HTTP status code errors: 4xx, 5xx)
├── ClientErrorException (4xx errors)
├── ServerErrorException (5xx errors)
└── APIException (Chargebee API errors)
├── InvalidRequestException (validation errors)
├── PaymentException (payment-related errors)
├── OperationFailedException (business logic errors)
├── BatchAPIException (batch operation errors)
└── UbbBatchIngestionInvalidRequestException (batch ingestion errors)
```

#### Exception Types

- **`ChargebeeException`**: Base exception for all SDK errors - catch-all for any Chargebee SDK error
- **`ConfigurationException`**: Thrown when SDK configuration is invalid (missing API key, invalid URL, etc.)
- **`TransportException`**: Base exception for all transport-layer failures (network issues, timeouts, etc.)
- **`HttpException`**: Thrown for HTTP error status codes (4xx, 5xx) - contains status code and response
- **`ClientErrorException`**: HTTP 4xx client errors (bad request, unauthorized, not found, etc.)
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group = "com.chargebee"
version = "4.0.0"
version = "4.0.0-beta.3"
description = "Next-gen Java client library for ChargeBee API"

// Project metadata
Expand All @@ -30,8 +30,8 @@ extra["projectLicenseUrl"] = projectLicenseUrl
extra["teamMembers"] = teamMembers

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
withSourcesJar()
withJavadocJar()
}
Expand Down
Binary file added dist/chargebee-java-4.0.0-beta.3-javadoc.jar
Binary file not shown.
Binary file added dist/chargebee-java-4.0.0-beta.3-sources.jar
Binary file not shown.
Binary file added dist/chargebee-java-4.0.0-beta.3.jar
Binary file not shown.
Binary file removed dist/chargebee-java-4.0.0-javadoc.jar
Binary file not shown.
Binary file removed dist/chargebee-java-4.0.0-sources.jar
Binary file not shown.
Binary file removed dist/chargebee-java-4.0.0.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The v4 SDK provides a modern, immutable client with enhanced type safety and imp
<dependency>
<groupId>com.chargebee</groupId>
<artifactId>chargebee-java</artifactId>
<version>4.0.0</version>
<version>4.0.0-beta.3</version>
</dependency>
```

Expand Down
21 changes: 11 additions & 10 deletions src/main/java/com/chargebee/v4/client/ChargebeeClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.chargebee.v4.client.request.RequestContext;
import com.chargebee.v4.client.request.RequestInterceptor;
import com.chargebee.v4.client.request.RequestWrap;
import com.chargebee.v4.exceptions.ChargebeeException;
import com.chargebee.v4.exceptions.ConfigurationException;
import com.chargebee.v4.exceptions.NetworkException;
import com.chargebee.v4.exceptions.TimeoutException;
Expand Down Expand Up @@ -109,9 +110,9 @@ public String getBaseUrl() {
* @param path the API path (e.g., "/customers")
* @param queryParams optional query parameters
* @return the HTTP response
* @throws Exception for network, timeout, configuration failures, or interceptor errors
* @throws ChargebeeException for network, timeout, configuration failures, or interceptor errors
*/
public Response get(String path, Map<String, List<String>> queryParams) throws Exception {
public Response get(String path, Map<String, List<String>> queryParams) throws ChargebeeException {
Map<String, Object> objectParams = new HashMap<>(queryParams);
String fullUrl = UrlBuilder.buildUrl(getBaseUrl(), path, objectParams);
Request.Builder builder = Request.builder()
Expand All @@ -130,9 +131,9 @@ public Response get(String path, Map<String, List<String>> queryParams) throws E
*
* @param path the API path (e.g., "/customers")
* @return the HTTP response
* @throws Exception for network, timeout, configuration failures, or interceptor errors
* @throws ChargebeeException for network, timeout, configuration failures, or interceptor errors
*/
public Response get(String path) throws Exception {
public Response get(String path) throws ChargebeeException {
return get(path, Collections.emptyMap());
}

Expand Down Expand Up @@ -173,9 +174,9 @@ public CompletableFuture<Response> getAsync(String path) {
* @param path the API path (e.g., "/customers")
* @param formData the form data to send
* @return the HTTP response
* @throws Exception for network, timeout, configuration failures, or interceptor errors
* @throws ChargebeeException for network, timeout, configuration failures, or interceptor errors
*/
public Response post(String path, Map<String, Object> formData) throws Exception {
public Response post(String path, Map<String, Object> formData) throws ChargebeeException {
String fullUrl = UrlBuilder.buildUrl(getBaseUrl(), path, null);
Request.Builder builder = Request.builder()
.method("POST")
Expand All @@ -195,9 +196,9 @@ public Response post(String path, Map<String, Object> formData) throws Exception
* @param path the API path (e.g., "/customers")
* @param jsonData the JSON data to send
* @return the HTTP response
* @throws Exception for network, timeout, configuration failures, or interceptor errors
* @throws ChargebeeException for network, timeout, configuration failures, or interceptor errors
*/
public Response postJson(String path, String jsonData) throws Exception {
public Response postJson(String path, String jsonData) throws ChargebeeException {
String fullUrl = UrlBuilder.buildUrl(getBaseUrl(), path, null);
Request.Builder builder = Request.builder()
.method("POST")
Expand Down Expand Up @@ -256,7 +257,7 @@ public CompletableFuture<Response> postJsonAsync(String path, String jsonData) {
/**
* Execute a request with optional interceptor.
*/
public Response executeWithInterceptor(Request request) throws Exception {
public Response executeWithInterceptor(Request request) throws ChargebeeException {
if (requestInterceptor != null) {
RequestWrap requestWrap = new RequestWrap(this, request);
return requestInterceptor.handleRequest(requestWrap);
Expand All @@ -280,7 +281,7 @@ public CompletableFuture<Response> executeWithInterceptorAsync(Request request)
/**
* Send a request with retry logic based on the configured RetryConfig.
*/
public Response sendWithRetry(Request request) throws TransportException {
public Response sendWithRetry(Request request) {
Request enrichedRequest = addDefaultHeaders(request);

Integer overrideRetries = enrichedRequest.getMaxNetworkRetriesOverride();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.chargebee.v4.client.request;

import com.chargebee.v4.exceptions.ChargebeeException;
import com.chargebee.v4.transport.Request;
import com.chargebee.v4.transport.Response;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -51,9 +52,9 @@ public interface RequestInterceptor {
*
* @param requestWrap wrapper containing the transport request and execution context
* @return the transport response, either from proceeding or custom implementation
* @throws Exception if request processing fails
* @throws ChargebeeException if request processing fails
*/
Response handleRequest(RequestWrap requestWrap) throws Exception;
Response handleRequest(RequestWrap requestWrap) throws ChargebeeException;

/**
* Handle the intercepted request asynchronously.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.chargebee.v4.client.request;

import com.chargebee.v4.client.ChargebeeClient;
import com.chargebee.v4.exceptions.ChargebeeException;
import com.chargebee.v4.transport.Request;
import com.chargebee.v4.transport.Response;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -95,9 +96,9 @@ public ChargebeeClient getClient() {
* standard request processing after any modifications.</p>
*
* @return the transport response from normal execution
* @throws Exception if request execution fails
* @throws ChargebeeException if request execution fails
*/
public Response proceed() throws Exception {
public Response proceed() throws ChargebeeException {
return call();
}

Expand All @@ -120,10 +121,10 @@ public CompletableFuture<Response> proceedAsync() {
* and transport layer.</p>
*
* @return the transport response
* @throws Exception if request execution fails
* @throws ChargebeeException if request execution fails
*/
@Override
public Response call() throws Exception {
public Response call() throws ChargebeeException {
return client.sendWithRetry(request);
}
}
7 changes: 4 additions & 3 deletions src/main/java/com/chargebee/v4/exceptions/APIException.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,12 @@ private String extractErrorCauseId(String jsonResponse) {

/**
* API errors are generally not retryable as they indicate business logic issues.
*
*
* <p>Exceptions that may warrant retry:
*
* <ul>
* <li>429 Too Many Requests - Rate limiting</li>
* <li>5xx Server errors - Temporary server issues</li>
* <li>429 Too Many Requests - Rate limiting
* <li>5xx Server errors - Temporary server issues
* </ul>
*
* @return true only for 429 or 5xx status codes
Expand Down
95 changes: 95 additions & 0 deletions src/main/java/com/chargebee/v4/exceptions/ChargebeeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.chargebee.v4.exceptions;

/**
* The root exception class for all errors originating from the Chargebee SDK.
*
* <p>{@code ChargebeeException} serves as the unified base for the SDK's exception hierarchy,
* enabling developers to catch all Chargebee-related errors with a single exception type
* while still allowing fine-grained handling of specific error categories.</p>
*
* <h2>Exception Hierarchy</h2>
* <pre>
* ChargebeeException
* ├── {@link ConfigurationException} — Invalid SDK configuration (missing API key, malformed URL)
* └── {@link TransportException} — Runtime communication errors
* ├── {@link NetworkException} — Connection failures, DNS resolution errors
* ├── {@link TimeoutException} — Connect or read timeout exceeded
* └── {@link HttpException} — HTTP-level errors (4xx, 5xx responses)
* ├── {@link ClientErrorException} — Client errors (400-499)
* ├── {@link ServerErrorException} — Server errors (500-599)
* └── {@link APIException} — Chargebee API errors with structured details
* </pre>
*
* <h2>Usage Patterns</h2>
*
* <h3>Catch-all handling</h3>
* <pre>{@code
* try {
* client.subscriptions().create(params);
* } catch (ChargebeeException e) {
* log.error("Chargebee operation failed: {}", e.getMessage());
* if (e.isRetryable()) {
* // Schedule retry
* }
* }
* }</pre>
*
* <h3>Granular error handling</h3>
* <pre>{@code
* try {
* client.subscriptions().create(params);
* } catch (InvalidRequestException e) {
* // Handle validation errors - check e.getParams() for invalid fields
* } catch (PaymentException e) {
* // Handle payment failures - check e.getErrorCauseId() for gateway details
* } catch (NetworkException | TimeoutException e) {
* // Handle transient failures - safe to retry
* } catch (ChargebeeException e) {
* // Fallback for unexpected SDK errors
* }
* }</pre>
*
* @see TransportException
* @see ConfigurationException
* @see APIException
*/
public class ChargebeeException extends RuntimeException {

/**
* Constructs a new exception with the specified detail message.
*
* @param message the detail message describing the error condition
*/
public ChargebeeException(String message) {
super(message);
}

/**
* Constructs a new exception with the specified detail message and cause.
*
* @param message the detail message describing the error condition
* @param cause the underlying exception that triggered this error
*/
public ChargebeeException(String message, Throwable cause) {
super(message, cause);
}

/**
* Indicates whether retrying the failed operation might succeed.
*
* <p>Subclasses override this method to provide accurate retry guidance:</p>
* <ul>
* <li>{@link NetworkException} — returns {@code true} (transient connectivity issues)</li>
* <li>{@link TimeoutException} — returns {@code true} (temporary overload)</li>
* <li>{@link ServerErrorException} — returns {@code true} for 5xx except 501</li>
* <li>{@link ClientErrorException} — returns {@code true} only for 429 (rate limited)</li>
* <li>{@link ConfigurationException} — returns {@code false} (requires code fix)</li>
* </ul>
*
* @return {@code true} if the operation may succeed on retry; {@code false} otherwise
*/
public boolean isRetryable() {
return false;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* Exception thrown when there's an issue with SDK configuration.
*
* <p>This is a runtime exception (unchecked) to allow fluent builder usage
* <p>This extends {@link ChargebeeException} to allow fluent builder usage
* without requiring try-catch blocks during client setup.
*
* <p>Common causes:
Expand All @@ -28,7 +28,7 @@
* <p>Note: This exception is NOT retryable as it indicates a programming error
* that must be fixed in the code.
*/
public class ConfigurationException extends RuntimeException {
public class ConfigurationException extends ChargebeeException {

/**
* Creates a ConfigurationException with a message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@
*
* <p>Exception hierarchy:
* <pre>
* TransportException
* ├── NetworkException (DNS failures, connection refused, I/O errors)
* ├── TimeoutException (connect/read timeouts)
* └── HttpException (HTTP status code errors: 4xx, 5xx)
* ├── ClientErrorException (4xx)
* ├── ServerErrorException (5xx)
* └── APIException (Chargebee API errors with structured response)
* ChargebeeException
* └── TransportException
* ├── NetworkException (DNS failures, connection refused, I/O errors)
* ├── TimeoutException (connect/read timeouts)
* └── HttpException (HTTP status code errors: 4xx, 5xx)
* ├── ClientErrorException (4xx)
* ├── ServerErrorException (5xx)
* └── APIException (Chargebee API errors with structured response)
* </pre>
*/
public class TransportException extends Exception {
public class TransportException extends ChargebeeException {

private final Request request;

Expand Down
Loading