CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-cdap-cdap--cdap-client

CDAP Java Client library providing programmatic APIs for interacting with the CDAP platform

Pending
Overview
Eval results
Files

application-management.mddocs/

Application Management

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.

ApplicationClient

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);
}

Application Types and Records

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();
}

Application Listing and Discovery

Basic Listing

// 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());
}

Paginated Listing

// 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);

Filtered Listing

// 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);

Application Details and Inspection

// 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");
}

Application Deployment

Deploy from JAR File

// 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);

Deploy from Artifact

// 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);

Deployment with Wait

// Deploy and wait for completion
appClient.deploy(namespace, jarFile);
appClient.waitForDeployed(newAppId, 60, TimeUnit.SECONDS);
System.out.println("Application deployed successfully");

Application Updates and Upgrades

Update Application Configuration

// 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 to Latest Artifact

// 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);

Application Deletion

// 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");

Program Management

List Programs

// 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);

Schedule Management

// 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);

Error Handling

Application management operations may throw these exceptions:

  • ApplicationNotFoundException: Application does not exist
  • ApplicationAlreadyExistsException: Application already exists during deployment
  • ArtifactNotFoundException: Referenced artifact does not exist
  • InvalidApplicationException: Invalid application configuration or structure
  • UnauthenticatedException: Authentication required
  • UnauthorizedException: Insufficient permissions
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());
}

Best Practices

  1. Version Management: Always specify application versions for production deployments
  2. Configuration Management: Use external configuration files rather than hardcoding values
  3. Gradual Rollouts: Test applications in development namespaces before production
  4. Cleanup: Regularly clean up old application versions to save storage
  5. Monitoring: Monitor application deployment status and handle failures gracefully
  6. Backup: Keep backup copies of application JAR files and configurations
// 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

docs

application-management.md

artifact-management.md

configuration.md

data-operations.md

dataset-operations.md

index.md

metrics-monitoring.md

program-control.md

schedule-management.md

security-administration.md

service-management.md

tile.json