CDAP Java Client library providing programmatic APIs for interacting with the CDAP platform
—
The ApplicationClient provides comprehensive application lifecycle management including deployment, updating, deletion, versioning, and program management. Applications are the primary deployment units in CDAP that contain one or more programs.
public class ApplicationClient {
// Constructors
public ApplicationClient(ClientConfig config);
public ApplicationClient(ClientConfig config, RESTClient restClient);
// Application listing methods
public List<ApplicationRecord> list(NamespaceId namespace);
public JsonObject paginatedList(NamespaceId namespace, String nextPageToken);
public List<ApplicationRecord> list(NamespaceId namespace, String artifactName, String artifactVersion, Boolean latestOnly);
public List<ApplicationRecord> list(NamespaceId namespace, Set<String> artifactNames, String artifactVersion, Boolean latestOnly);
public List<String> listAppVersions(NamespaceId namespace, String appName);
// Application details methods
public ApplicationDetail get(ApplicationId appId);
public ApplicationDetail get(ApplicationId appId, boolean latestOnly);
public List<PluginInstanceDetail> getPlugins(ApplicationId appId);
public boolean exists(ApplicationId app);
// Application lifecycle methods
public void deploy(NamespaceId namespace, File jarFile);
public void deploy(NamespaceId namespace, File jarFile, String appConfig);
public void deploy(NamespaceId namespace, File jarFile, String appConfig, String ownerPrincipal);
public void deploy(NamespaceId namespace, File jarFile, Config appConfig);
public void deploy(ApplicationId appId, AppRequest<?> createRequest);
public void update(ApplicationId appId, AppRequest<?> updateRequest);
public void upgradeApplication(ApplicationId app);
public void upgradeApplication(ApplicationId app, Set<String> artifactScopes, boolean allowSnapshot);
public void delete(ApplicationId app);
public void deleteApp(ApplicationId app);
public void deleteAll(NamespaceId namespace);
// Program management methods
public List<ProgramRecord> listAllPrograms(NamespaceId namespace, ProgramType programType);
public Map<ProgramType, List<ProgramRecord>> listAllPrograms(NamespaceId namespace);
public List<ProgramRecord> listPrograms(ApplicationId app, ProgramType programType);
public Map<ProgramType, List<ProgramRecord>> listProgramsByType(ApplicationId app);
public List<ProgramRecord> listPrograms(ApplicationId app);
// Schedule management methods
public void addSchedule(ApplicationId app, ScheduleDetail scheduleDetail);
public void enableSchedule(ScheduleId scheduleId);
// Utility methods
public void waitForDeployed(ApplicationId app, long timeout, TimeUnit timeoutUnit);
public void waitForDeleted(ApplicationId app, long timeout, TimeUnit timeoutUnit);
}public class ApplicationRecord {
public String getName();
public String getAppVersion();
public String getDescription();
public ArtifactSummary getArtifact();
public String getOwnerPrincipal();
public long getCreationTimeMillis();
}
public class ApplicationDetail {
public String getName();
public String getAppVersion();
public String getDescription();
public ApplicationSpecification getSpec();
public ArtifactSummary getArtifact();
public String getOwnerPrincipal();
public long getCreationTimeMillis();
public Map<String, String> getConfiguration();
}
public class PluginInstanceDetail {
public String getName();
public String getType();
public ArtifactSummary getArtifact();
public Map<String, String> getProperties();
}
public class AppRequest<T> {
public AppRequest(ArtifactSummary artifact);
public AppRequest(ArtifactSummary artifact, T config);
public ArtifactSummary getArtifact();
public T getConfig();
}// List all applications in default namespace
NamespaceId namespace = NamespaceId.DEFAULT;
List<ApplicationRecord> apps = appClient.list(namespace);
System.out.println("Found " + apps.size() + " applications:");
for (ApplicationRecord app : apps) {
System.out.println("- " + app.getName() + " v" + app.getAppVersion());
System.out.println(" Artifact: " + app.getArtifact().getName() + " v" + app.getArtifact().getVersion());
System.out.println(" Owner: " + app.getOwnerPrincipal());
}// Get paginated list of applications
String nextPageToken = null;
do {
JsonObject page = appClient.paginatedList(namespace, nextPageToken);
JsonArray applications = page.getAsJsonArray("applications");
for (JsonElement appElement : applications) {
JsonObject app = appElement.getAsJsonObject();
System.out.println("App: " + app.get("name").getAsString());
}
nextPageToken = page.has("nextPageToken") ?
page.get("nextPageToken").getAsString() : null;
} while (nextPageToken != null);// List applications by artifact
List<ApplicationRecord> sparkApps = appClient.list(
namespace,
"cdap-spark", // artifact name
"1.0.0", // artifact version
true // latest only
);
// List applications by multiple artifacts
Set<String> artifactNames = Set.of("cdap-spark", "cdap-mapreduce");
List<ApplicationRecord> dataApps = appClient.list(
namespace,
artifactNames,
"1.0.0",
false // all versions
);
// List all versions of a specific application
String appName = "my-analytics-app";
List<String> versions = appClient.listAppVersions(namespace, appName);
System.out.println("Versions of " + appName + ": " + versions);// Get detailed application information
ApplicationId appId = ApplicationId.of(namespace, "my-app", "1.0.0");
ApplicationDetail detail = appClient.get(appId);
System.out.println("Application: " + detail.getName());
System.out.println("Version: " + detail.getAppVersion());
System.out.println("Description: " + detail.getDescription());
System.out.println("Artifact: " + detail.getArtifact().getName());
System.out.println("Configuration: " + detail.getConfiguration());
// Get application specification
ApplicationSpecification spec = detail.getSpec();
System.out.println("Programs: " + spec.getPrograms().keySet());
System.out.println("Datasets: " + spec.getDatasets().keySet());
// Get plugins used by the application
List<PluginInstanceDetail> plugins = appClient.getPlugins(appId);
for (PluginInstanceDetail plugin : plugins) {
System.out.println("Plugin: " + plugin.getName() + " (type: " + plugin.getType() + ")");
System.out.println(" Artifact: " + plugin.getArtifact().getName());
System.out.println(" Properties: " + plugin.getProperties());
}
// Check if application exists
boolean exists = appClient.exists(appId);
if (exists) {
System.out.println("Application exists");
}// Basic deployment from JAR file
File jarFile = new File("/path/to/my-app.jar");
appClient.deploy(namespace, jarFile);
// Deploy with configuration
String appConfig = "{\"config.key\": \"config.value\"}";
appClient.deploy(namespace, jarFile, appConfig);
// Deploy with configuration and owner
String owner = "data-team@company.com";
appClient.deploy(namespace, jarFile, appConfig, owner);
// Deploy with Config object
Config configObj = new MyAppConfig("value1", "value2");
appClient.deploy(namespace, jarFile, configObj);// Create application from existing artifact
ArtifactSummary artifact = new ArtifactSummary("my-artifact", "1.0.0", ArtifactScope.USER);
AppRequest<Map<String, String>> createRequest = new AppRequest<>(artifact);
ApplicationId newAppId = ApplicationId.of(namespace, "my-new-app", "1.0.0");
appClient.deploy(newAppId, createRequest);
// Deploy with configuration
Map<String, String> config = Map.of(
"input.path", "/data/input",
"output.path", "/data/output",
"batch.size", "1000"
);
AppRequest<Map<String, String>> configuredRequest = new AppRequest<>(artifact, config);
appClient.deploy(newAppId, configuredRequest);// Deploy and wait for completion
appClient.deploy(namespace, jarFile);
appClient.waitForDeployed(newAppId, 60, TimeUnit.SECONDS);
System.out.println("Application deployed successfully");// Update existing application with new configuration
Map<String, String> newConfig = Map.of(
"updated.parameter", "new-value",
"batch.size", "2000"
);
ArtifactSummary currentArtifact = new ArtifactSummary("my-artifact", "1.0.0", ArtifactScope.USER);
AppRequest<Map<String, String>> updateRequest = new AppRequest<>(currentArtifact, newConfig);
appClient.update(appId, updateRequest);// Upgrade application to latest compatible artifact version
appClient.upgradeApplication(appId);
// Upgrade with specific options
Set<String> scopes = Set.of("USER", "SYSTEM");
boolean allowSnapshot = true;
appClient.upgradeApplication(appId, scopes, allowSnapshot);// Delete specific application version
appClient.delete(appId);
// Delete all versions of an application
ApplicationId allVersionsId = ApplicationId.of(namespace, "my-app");
appClient.deleteApp(allVersionsId);
// Delete all applications in namespace (use with caution!)
appClient.deleteAll(namespace);
// Delete with wait confirmation
appClient.delete(appId);
appClient.waitForDeleted(appId, 30, TimeUnit.SECONDS);
System.out.println("Application deleted successfully");// List all programs in an application
List<ProgramRecord> allPrograms = appClient.listPrograms(appId);
for (ProgramRecord program : allPrograms) {
System.out.println("Program: " + program.getName() + " (type: " + program.getType() + ")");
}
// List programs by type
List<ProgramRecord> workflows = appClient.listPrograms(appId, ProgramType.WORKFLOW);
List<ProgramRecord> services = appClient.listPrograms(appId, ProgramType.SERVICE);
// List programs grouped by type
Map<ProgramType, List<ProgramRecord>> programsByType = appClient.listProgramsByType(appId);
for (Map.Entry<ProgramType, List<ProgramRecord>> entry : programsByType.entrySet()) {
System.out.println(entry.getKey() + " programs: " + entry.getValue().size());
}
// List all programs of a specific type across all applications in namespace
List<ProgramRecord> allServices = appClient.listAllPrograms(namespace, ProgramType.SERVICE);
// List all programs across all applications in namespace
Map<ProgramType, List<ProgramRecord>> allPrograms = appClient.listAllPrograms(namespace);// Add schedule to application
ScheduleDetail scheduleDetail = ScheduleDetail.builder()
.setName("daily-schedule")
.setDescription("Run daily at midnight")
.setTrigger(new TimeTrigger("0 0 * * *")) // Cron expression
.setProgram(ProgramId.of(appId, ProgramType.WORKFLOW, "data-processing"))
.build();
appClient.addSchedule(appId, scheduleDetail);
// Enable the schedule
ScheduleId scheduleId = ScheduleId.of(appId, "daily-schedule");
appClient.enableSchedule(scheduleId);Application management operations may throw these exceptions:
try {
ApplicationDetail detail = appClient.get(appId);
System.out.println("Application found: " + detail.getName());
} catch (ApplicationNotFoundException e) {
System.err.println("Application not found: " + appId);
} catch (UnauthorizedException e) {
System.err.println("No permission to access application: " + e.getMessage());
} catch (IOException e) {
System.err.println("Network error: " + e.getMessage());
}// Good: Explicit version management
ApplicationId prodApp = ApplicationId.of(
NamespaceId.of("production"),
"analytics-app",
"2.1.0"
);
// Good: Configuration from external source
Properties config = loadConfigFromFile("app-config.properties");
Map<String, String> appConfig = config.entrySet().stream()
.collect(Collectors.toMap(
e -> (String) e.getKey(),
e -> (String) e.getValue()
));
// Good: Error handling with retry logic
int maxRetries = 3;
for (int i = 0; i < maxRetries; i++) {
try {
appClient.deploy(namespace, jarFile, appConfig);
System.out.println("Deployment successful");
break;
} catch (IOException e) {
if (i == maxRetries - 1) {
throw new RuntimeException("Deployment failed after " + maxRetries + " attempts", e);
}
System.out.println("Deployment attempt " + (i + 1) + " failed, retrying...");
Thread.sleep(5000); // Wait 5 seconds before retry
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-cdap-cdap--cdap-client