Configuring Thread-Safe HTTP Connection Pooling for the Genesys Cloud Java SDK
What You Will Build
- A production-ready Java utility class that initializes a thread-safe, connection-pooled
ApiClientinstance for the Genesys Cloud Platform SDK. - An implementation that handles OAuth2 token refresh asynchronously without blocking application threads.
- A demonstration of executing parallel API requests using the configured client.
Prerequisites
- OAuth Client Type: Confidential Client (Client Credentials Grant).
- Required Scopes:
view:users(for the example query),offline_access(optional but recommended for token caching strategies). - SDK Version:
genesyscloud-platform-java-clientversion 13.0.0 or later. - Language/Runtime: Java 11 or higher.
- External Dependencies:
com.twilio:genesyscloud-platform-java-clientorg.apache.httpcomponents:httpclient(managed by SDK, but good to know)org.slf4j:slf4j-api(for logging)
Authentication Setup
The Genesys Cloud Java SDK relies on the ApiClient class to manage HTTP connections and authentication tokens. By default, the SDK creates a new HTTP client instance for each ApiClient initialization, which is inefficient for high-throughput applications. To implement connection pooling, you must manually configure the underlying Apache HttpClient and inject it into the SDK.
The authentication flow uses the Client Credentials Grant. The SDK handles the token retrieval and refresh automatically, provided you supply the correct credentials. However, because the token refresh mechanism is internal to the ApiClient, you must ensure that the ApiClient instance is shared across threads to avoid redundant token requests and connection churn.
Step 1: Initialize the Thread-Safe ApiClient with Connection Pooling
The core of this tutorial is creating a singleton or static instance of ApiClient that uses a shared PoolingHttpClientConnectionManager. This manager maintains a pool of reusable connections, reducing latency for subsequent requests and preventing socket exhaustion under load.
import com.mypurecloud.v2.ApiClient;
import com.mypurecloud.v2.auth.OAuth;
import com.mypurecloud.v2.auth.OAuthFlow;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import java.security.KeyStore;
import java.io.FileInputStream;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.io.IOException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
public class GenesysClientFactory {
private static volatile ApiClient apiClient;
private static final String REGION = "mypurecloud.com";
private static final String CLIENT_ID = System.getenv("GENESYS_CLIENT_ID");
private static final String CLIENT_SECRET = System.getenv("GENESYS_CLIENT_SECRET");
// Private constructor to prevent instantiation
private GenesysClientFactory() {}
/**
* Returns a thread-safe ApiClient instance with connection pooling.
* Uses double-checked locking for efficient synchronization.
*/
public static ApiClient getApiClient() {
if (apiClient == null) {
synchronized (GenesysClientFactory.class) {
if (apiClient == null) {
apiClient = createPooledApiClient();
}
}
}
return apiClient;
}
private static ApiClient createPooledApiClient() {
try {
// 1. Create an SSL Context (using default trust store for simplicity)
SSLContext sslContext = SSLContexts.createDefault();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
// 2. Register socket factories for HTTP and HTTPS
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
// 3. Initialize the Connection Pool
// Max total connections: 200
// Max connections per route: 20
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(20);
// 4. Build the HttpClient with the connection manager
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
// 5. Initialize the Genesys API Client
// Base URL for the Genesys Platform
String baseUrl = "https://" + REGION;
apiClient = new ApiClient(baseUrl);
// 6. Inject the custom HttpClient into the API Client
// This replaces the default HTTP client with our pooled one
apiClient.setHttpClient(httpClient);
// 7. Configure OAuth
OAuth oAuth = apiClient.getOAuth();
oAuth.setClientId(CLIENT_ID);
oAuth.setClientSecret(CLIENT_SECRET);
oAuth.setOAuthFlow(OAuthFlow.CLIENT_CREDENTIALS);
// Optional: Set a custom token refresh threshold (default is usually sufficient)
// oAuth.setAccessTokenRefreshThresholdSeconds(60);
// Initialize the OAuth token immediately
oAuth.init();
return apiClient;
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException
| CertificateException | IOException e) {
throw new RuntimeException("Failed to initialize Genesys API Client", e);
}
}
}
Step 2: Implementing Parallel API Requests
With a thread-safe ApiClient in place, you can now make multiple concurrent requests. The SDK methods are not thread-safe by themselves, but the underlying HTTP client and the OAuth token manager within ApiClient are designed to be shared.
Critical Note: Do not create a new UsersApi or other API wrapper instance for every thread. Instead, create a single instance of the API wrapper per thread, or reuse it if you ensure proper synchronization (though per-thread instances are safer and easier). The ApiClient itself must be shared.
Here is an example of fetching user details for multiple users in parallel using Java’s CompletableFuture.
import com.mypurecloud.v2.ApiClient;
import com.mypurecloud.v2.api.UsersApi;
import com.mypurecloud.v2.model.User;
import com.mypurecloud.v2.model.UserSearchResponse;
import com.mypurecloud.v2.auth.OAuth;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
public class ParallelUserFetcher {
private final ApiClient apiClient;
private final ExecutorService executor;
public ParallelUserFetcher(ApiClient apiClient, int threadCount) {
this.apiClient = apiClient;
this.executor = Executors.newFixedThreadPool(threadCount);
}
/**
* Fetches user details for a list of user IDs concurrently.
*
* @param userIds List of user IDs to fetch
* @return List of User objects
*/
public List<User> fetchUsersConcurrently(List<String> userIds) {
List<CompletableFuture<User>> futures = new ArrayList<>();
for (String userId : userIds) {
// Create a new API instance for each thread/task to ensure thread safety
// The ApiClient is shared, but the API wrapper should not be shared across threads
UsersApi usersApi = new UsersApi(apiClient);
CompletableFuture<User> future = CompletableFuture.supplyAsync(() -> {
try {
// Fetch user details
// Scope: view:users
return usersApi.getUser(userId);
} catch (Exception e) {
// Handle 404, 429, or network errors
System.err.println("Error fetching user " + userId + ": " + e.getMessage());
return null;
}
}, executor);
futures.add(future);
}
// Wait for all futures to complete and collect results
return futures.stream()
.map(CompletableFuture::join)
.filter(user -> user != null)
.collect(Collectors.toList());
}
public void shutdown() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
Step 3: Handling Rate Limits (429) and Retries
Even with connection pooling, you will hit rate limits. The Genesys Cloud API returns 429 Too Many Requests when you exceed the allowed rate. The Java SDK does not automatically retry 429 errors by default in all versions, so implementing a retry mechanism with exponential backoff is crucial for production stability.
You can extend the ApiClient or use a wrapper to handle retries. Here is a simple retry utility that wraps the API call.
import java.io.IOException;
import java.net.http.HttpTimeoutException;
import java.time.Duration;
@FunctionalInterface
interface ApiCall<T> {
T execute() throws Exception;
}
public class RetryUtils {
private static final int MAX_RETRIES = 3;
private static final long INITIAL_BACKOFF_MS = 1000;
/**
* Executes an API call with exponential backoff on 429 or 5xx errors.
*
* @param apiCall The API call to execute
* @param <T> The return type of the API call
* @return The result of the API call
* @throws Exception If the call fails after max retries
*/
public static <T> T executeWithRetry(ApiCall<T> apiCall) throws Exception {
Exception lastException = null;
long backoff = INITIAL_BACKOFF_MS;
for (int attempt = 0; attempt <= MAX_RETRIES; attempt++) {
try {
return apiCall.execute();
} catch (com.mypurecloud.v2.ApiException e) {
// Check for 429 Too Many Requests or 5xx Server Errors
if (e.getCode() == 429 || (e.getCode() >= 500 && e.getCode() < 600)) {
lastException = e;
System.out.println("Retry attempt " + (attempt + 1) + " after " + e.getCode() + " error. Waiting " + backoff + "ms...");
Thread.sleep(backoff);
backoff *= 2; // Exponential backoff
} else {
// Other errors (401, 403, 404) should not be retried
throw e;
}
} catch (IOException e) {
lastException = e;
System.out.println("Retry attempt " + (attempt + 1) + " after IOException. Waiting " + backoff + "ms...");
Thread.sleep(backoff);
backoff *= 2;
}
}
throw new RuntimeException("API call failed after " + MAX_RETRIES + " retries", lastException);
}
}
To use this, wrap your API calls:
User user = RetryUtils.executeWithRetry(() -> usersApi.getUser(userId));
Complete Working Example
This example combines all the previous steps into a single runnable class. It initializes the pooled client, fetches a list of users, and then fetches detailed information for each user in parallel with retry logic.
import com.mypurecloud.v2.ApiClient;
import com.mypurecloud.v2.api.UsersApi;
import com.mypurecloud.v2.model.User;
import com.mypurecloud.v2.model.UserSearchResponse;
import com.mypurecloud.v2.auth.OAuth;
import com.mypurecloud.v2.auth.OAuthFlow;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
public class GenesysPoolExample {
public static void main(String[] args) {
// Initialize the pooled API client
ApiClient apiClient = GenesysClientFactory.getApiClient();
// Create a parallel fetcher with 10 threads
ParallelUserFetcher fetcher = new ParallelUserFetcher(apiClient, 10);
try {
// Step 1: Search for users to get IDs
UsersApi usersApi = new UsersApi(apiClient);
String query = "divisionId:*"; // Search all users in all divisions
UserSearchResponse searchResponse = usersApi.postUsersSearch(
query,
null, // email
10, // pageSize
null, // page
null, // sortBy
null, // sortOrder
null, // expansion
null, // divisionId
null, // userId
null, // groupId
null, // roleIds
null, // queueIds
null, // skillIds
null, // languageIds
null, // presenceIds
null, // customAttributeIds
null, // customAttributeValues
null, // customAttributeFilter
null, // customAttributeFilterType
null, // customAttributeFilterValue
null, // customAttributeFilterOperator
null, // customAttributeFilterCondition
null, // customAttributeFilterConditionType
null, // customAttributeFilterConditionValue
null, // customAttributeFilterConditionOperator
null, // customAttributeFilterConditionCondition
null, // customAttributeFilterConditionConditionType
null, // customAttributeFilterConditionConditionValue
null, // customAttributeFilterConditionConditionOperator
null, // customAttributeFilterConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionType
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionValue
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionOperator
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition
null, // customAttributeFilterConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionConditionCondition