Generated banner for Azure Compute Batch Java
Generated logo for Azure Compute Batch Java

Azure Compute Batch Java

MicrosoftOfficialCreated by Microsoft

  • Skill
  • Tool integration
  • Cloud and DevOps
  • MIT
  • No issues found

From the author

Azure Batch SDK for Java. Run large-scale parallel and HPC batch jobs with pools, jobs, tasks, and compute nodes. Triggers: "BatchClient java", "azure batch java", "batch pool java", "batch job java", "HPC java", "parallel computing java".
— the description by Microsoft

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The Azure Batch SDK for Java provides a programmatic interface to interact with Azure Batch services. It enables developers to manage compute pools, define job schedules, and execute parallel or high-performance computing tasks across collections of virtual machine nodes. The library supports both synchronous and asynchronous client patterns and offers multiple authentication methods, including Microsoft Entra ID and shared key credentials.

What it does

  • Creates and manages compute pools of virtual machines
  • Defines and schedules batch jobs and individual tasks
  • Supports task collection submission for efficient processing
  • Provides monitoring for job progress and task execution status
  • Enables node management including reboots and remote access
  • Supports auto-scaling configurations for compute resources

When to use it

  • When building Java applications that require large-scale parallel processing
  • When automating high-performance computing workflows on Azure
  • When you need to dynamically manage compute resources based on task volume
  • When integrating batch job scheduling into existing Java services

Advantages

  • Native Java support for Azure Batch service operations
  • Flexible authentication options including Entra ID
  • Support for both synchronous and asynchronous programming models
  • Comprehensive control over task lifecycle and exit conditions

Usage examples

“How do I create a new batch pool using the Java SDK?”
The agent provides a code snippet using BatchPoolCreateParameters to define pool ID, VM configuration, and node counts, then calls createPool on the BatchClient.
“Show me how to submit multiple tasks to an Azure Batch job in Java.”
The agent demonstrates using createTaskCollection or createTasks to batch multiple BatchTaskCreateParameters objects into a single request.
“How can I retrieve the output of a specific task in Azure Batch?”
The agent shows how to use getTaskFile with the job ID, task ID, and file name to retrieve task output as BinaryData.
“How do I authenticate the BatchClient using Entra ID?”
The agent provides a code example using DefaultAzureCredentialBuilder to configure the BatchClientBuilder for secure authentication.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/microsoft/azure-compute-batch-java/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip azure-compute-batch-java.zip -d .agents/skills

Documentation by Microsoft

Azure Batch SDK for Java

Client library for running large-scale parallel and high-performance computing (HPC) batch jobs in Azure.

Installation

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-compute-batch</artifactId>
    <version>1.0.0-beta.5</version>
</dependency>

Prerequisites

  • Azure Batch account

  • Pool configured with compute nodes

  • Azure subscription

Environment Variables

AZURE_BATCH_ENDPOINT=https://<account>.<region>.batch.azure.com  # Required for all auth methods
AZURE_BATCH_ACCOUNT=<account-name>  # Only required for shared key auth
AZURE_BATCH_ACCESS_KEY=<account-key>  # Only required for shared key auth
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production

Client Creation

import com.azure.compute.batch.BatchClient;
import com.azure.compute.batch.BatchClientBuilder;
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();

BatchClient batchClient = new BatchClientBuilder()
    .credential(credential)
    .endpoint(System.getenv("AZURE_BATCH_ENDPOINT"))
    .buildClient();
Async Client
import com.azure.compute.batch.BatchAsyncClient;

BatchAsyncClient batchAsyncClient = new BatchClientBuilder()
    .credential(credential)
    .endpoint(System.getenv("AZURE_BATCH_ENDPOINT"))
    .buildAsyncClient();
With Shared Key Credentials
import com.azure.core.credential.AzureNamedKeyCredential;

String accountName = System.getenv("AZURE_BATCH_ACCOUNT");
String accountKey = System.getenv("AZURE_BATCH_ACCESS_KEY");
AzureNamedKeyCredential sharedKeyCreds = new AzureNamedKeyCredential(accountName, accountKey);

BatchClient batchClient = new BatchClientBuilder()
    .credential(sharedKeyCreds)
    .endpoint(System.getenv("AZURE_BATCH_ENDPOINT"))
    .buildClient();

Key Concepts

ConceptDescription
PoolCollection of compute nodes that run tasks
JobLogical grouping of tasks
TaskUnit of computation (command/script)
NodeVM that executes tasks
Job ScheduleRecurring job creation

Pool Operations

Create Pool
import com.azure.compute.batch.models.*;

batchClient.createPool(new BatchPoolCreateParameters("myPoolId", "STANDARD_DC2s_V2")
    .setVirtualMachineConfiguration(
        new VirtualMachineConfiguration(
            new BatchVmImageReference()
                .setPublisher("Canonical")
                .setOffer("UbuntuServer")
                .setSku("22_04-lts")
                .setVersion("latest"),
            "batch.node.ubuntu 22.04"))
    .setTargetDedicatedNodes(2)
    .setTargetLowPriorityNodes(0), null);
Get Pool
BatchPool pool = batchClient.getPool("myPoolId");
System.out.println("Pool state: " + pool.getState());
System.out.println("Current dedicated nodes: " + pool.getCurrentDedicatedNodes());
List Pools
import com.azure.core.http.rest.PagedIterable;

PagedIterable<BatchPool> pools = batchClient.listPools();
for (BatchPool pool : pools) {
    System.out.println("Pool: " + pool.getId() + ", State: " + pool.getState());
}
Resize Pool
import com.azure.core.util.polling.SyncPoller;

BatchPoolResizeParameters resizeParams = new BatchPoolResizeParameters()
    .setTargetDedicatedNodes(4)
    .setTargetLowPriorityNodes(2);

SyncPoller<BatchPool, BatchPool> poller = batchClient.beginResizePool("myPoolId", resizeParams);
poller.waitForCompletion();
BatchPool resizedPool = poller.getFinalResult();
Enable AutoScale
BatchPoolEnableAutoScaleParameters autoScaleParams = new BatchPoolEnableAutoScaleParameters()
    .setAutoScaleEvaluationInterval(Duration.ofMinutes(5))
    .setAutoScaleFormula("$TargetDedicatedNodes = min(10, $PendingTasks.GetSample(TimeInterval_Minute * 5));");

batchClient.enablePoolAutoScale("myPoolId", autoScaleParams);
Delete Pool
SyncPoller<BatchPool, Void> deletePoller = batchClient.beginDeletePool("myPoolId");
deletePoller.waitForCompletion();

Job Operations

Create Job
batchClient.createJob(
    new BatchJobCreateParameters("myJobId", new BatchPoolInfo().setPoolId("myPoolId"))
        .setPriority(100)
        .setConstraints(new BatchJobConstraints()
            .setMaxWallClockTime(Duration.ofHours(24))
            .setMaxTaskRetryCount(3)),
    null);
Get Job
BatchJob job = batchClient.getJob("myJobId", null, null);
System.out.println("Job state: " + job.getState());
List Jobs
PagedIterable<BatchJob> jobs = batchClient.listJobs(new BatchJobsListOptions());
for (BatchJob job : jobs) {
    System.out.println("Job: " + job.getId() + ", State: " + job.getState());
}
Get Task Counts
BatchTaskCountsResult counts = batchClient.getJobTaskCounts("myJobId");
System.out.println("Active: " + counts.getTaskCounts().getActive());
System.out.println("Running: " + counts.getTaskCounts().getRunning());
System.out.println("Completed: " + counts.getTaskCounts().getCompleted());
Terminate Job
BatchJobTerminateParameters terminateParams = new BatchJobTerminateParameters()
    .setTerminationReason("Manual termination");
BatchJobTerminateOptions options = new BatchJobTerminateOptions().setParameters(terminateParams);

SyncPoller<BatchJob, BatchJob> poller = batchClient.beginTerminateJob("myJobId", options, null);
poller.waitForCompletion();
Delete Job
SyncPoller<BatchJob, Void> deletePoller = batchClient.beginDeleteJob("myJobId");
deletePoller.waitForCompletion();

Task Operations

Create Single Task
BatchTaskCreateParameters task = new BatchTaskCreateParameters("task1", "echo 'Hello World'");
batchClient.createTask("myJobId", task);
Create Task with Exit Conditions
batchClient.createTask("myJobId", new BatchTaskCreateParameters("task2", "cmd /c exit 3")
    .setExitConditions(new ExitConditions()
        .setExitCodeRanges(Arrays.asList(
            new ExitCodeRangeMapping(2, 4, 
                new ExitOptions().setJobAction(BatchJobActionKind.TERMINATE)))))
    .setUserIdentity(new UserIdentity()
        .setAutoUser(new AutoUserSpecification()
            .setScope(AutoUserScope.TASK)
            .setElevationLevel(ElevationLevel.NON_ADMIN))),
    null);
Create Task Collection (up to 100)
List<BatchTaskCreateParameters> taskList = Arrays.asList(
    new BatchTaskCreateParameters("task1", "echo Task 1"),
    new BatchTaskCreateParameters("task2", "echo Task 2"),
    new BatchTaskCreateParameters("task3", "echo Task 3")
);
BatchTaskGroup taskGroup = new BatchTaskGroup(taskList);
BatchCreateTaskCollectionResult result = batchClient.createTaskCollection("myJobId", taskGroup);
Create Many Tasks (no limit)
List<BatchTaskCreateParameters> tasks = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
    tasks.add(new BatchTaskCreateParameters("task" + i, "echo Task " + i));
}
batchClient.createTasks("myJobId", tasks);
Get Task
BatchTask task = batchClient.getTask("myJobId", "task1");
System.out.println("Task state: " + task.getState());
System.out.println("Exit code: " + task.getExecutionInfo().getExitCode());
List Tasks
PagedIterable<BatchTask> tasks = batchClient.listTasks("myJobId");
for (BatchTask task : tasks) {
    System.out.println("Task: " + task.getId() + ", State: " + task.getState());
}
Get Task Output
import com.azure.core.util.BinaryData;
import java.nio.charset.StandardCharsets;

BinaryData stdout = batchClient.getTaskFile("myJobId", "task1", "stdout.txt");
System.out.println(new String(stdout.toBytes(), StandardCharsets.UTF_8));
Terminate Task
batchClient.terminateTask("myJobId", "task1", null, null);

Node Operations

List Nodes
PagedIterable<BatchNode> nodes = batchClient.listNodes("myPoolId", new BatchNodesListOptions());
for (BatchNode node : nodes) {
    System.out.println("Node: " + node.getId() + ", State: " + node.getState());
}
Reboot Node
SyncPoller<BatchNode, BatchNode> rebootPoller = batchClient.beginRebootNode("myPoolId", "nodeId");
rebootPoller.waitForCompletion();
Get Remote Login Settings
BatchNodeRemoteLoginSettings settings = batchClient.getNodeRemoteLoginSettings("myPoolId", "nodeId");
System.out.println("IP: " + settings.getRemoteLoginIpAddress());
System.out.println("Port: " + settings.getRemoteLoginPort());

Job Schedule Operations

Create Job Schedule
batchClient.createJobSchedule(new BatchJobScheduleCreateParameters("myScheduleId",
    new BatchJobScheduleConfiguration()
        .setRecurrenceInterval(Duration.ofHours(6))
        .setDoNotRunUntil(OffsetDateTime.now().plusDays(1)),
    new BatchJobSpecification(new BatchPoolInfo().setPoolId("myPoolId"))
        .setPriority(50)),
    null);
Get Job Schedule
BatchJobSchedule schedule = batchClient.getJobSchedule("myScheduleId");
System.out.println("Schedule state: " + schedule.getState());

Error Handling

import com.azure.compute.batch.models.BatchErrorException;
import com.azure.compute.batch.models.BatchError;

try {
    batchClient.getPool("nonexistent-pool");
} catch (BatchErrorException e) {
    BatchError error = e.getValue();
    System.err.println("Error code: " + error.getCode());
    System.err.println("Message: " + error.getMessage().getValue());
    
    if ("PoolNotFound".equals(error.getCode())) {
        System.err.println("The specified pool does not exist.");
    }
}

Best Practices

  1. Use Entra ID — Preferred over shared key for authentication

  2. Use management SDK for pools — azure-resourcemanager-batch supports managed identities

  3. Batch task creation — Use createTaskCollection or createTasks for multiple tasks

  4. Handle LRO properly — Pool resize, delete operations are long-running

  5. Monitor task counts — Use getJobTaskCounts to track progress

  6. Set constraints — Configure maxWallClockTime and maxTaskRetryCount

  7. Use low-priority nodes — Cost savings for fault-tolerant workloads

  8. Enable autoscale — Dynamically adjust pool size based on workload

Files

references/examples.md

Azure Batch Java SDK - Examples

Comprehensive code examples for the Azure Batch SDK for Java.

Table of Contents

  • Maven Dependency

  • Client Creation

  • Pool Operations

  • Job Operations

  • Task Operations

  • Node Operations

  • Job Schedule Operations

  • Error Handling

  • Complete Application Example

Maven Dependency

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-compute-batch</artifactId>
    <version>1.0.0-beta.5</version>
</dependency>

<!-- For DefaultAzureCredential -->
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.14.2</version>
</dependency>

Client Creation

import com.azure.compute.batch.BatchClient;
import com.azure.compute.batch.BatchClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;

String endpoint = System.getenv("AZURE_BATCH_ENDPOINT");

BatchClient batchClient = new BatchClientBuilder()
    .credential(new DefaultAzureCredentialBuilder().build())
    .endpoint(endpoint)
    .buildClient();
Async Client
import com.azure.compute.batch.BatchAsyncClient;

BatchAsyncClient batchAsyncClient = new BatchClientBuilder()
    .credential(new DefaultAzureCredentialBuilder().build())
    .endpoint(endpoint)
    .buildAsyncClient();
With Shared Key Credentials
import com.azure.core.credential.AzureNamedKeyCredential;

String accountName = System.getenv("AZURE_BATCH_ACCOUNT");
String accountKey = System.getenv("AZURE_BATCH_ACCESS_KEY");

AzureNamedKeyCredential sharedKeyCreds = new AzureNamedKeyCredential(accountName, accountKey);

BatchClient batchClient = new BatchClientBuilder()
    .credential(sharedKeyCreds)
    .endpoint(endpoint)
    .buildClient();

Pool Operations

Create Pool
import com.azure.compute.batch.models.*;

batchClient.createPool(new BatchPoolCreateParameters("myPoolId", "STANDARD_DC2s_v2")
    .setVirtualMachineConfiguration(
        new VirtualMachineConfiguration(
            new BatchVmImageReference()
                .setPublisher("Canonical")
                .setOffer("UbuntuServer")
                .setSku("22_04-lts")
                .setVersion("latest"),
            "batch.node.ubuntu 22.04"))
    .setTargetDedicatedNodes(2)
    .setTargetLowPriorityNodes(0)
    .setTaskSlotsPerNode(4)
    .setTaskSchedulingPolicy(new TaskSchedulingPolicy(ComputeNodeFillType.SPREAD)), null);

System.out.println("Pool created: myPoolId");
Create Pool with Start Task
batchClient.createPool(new BatchPoolCreateParameters("myPoolWithStartTask", "STANDARD_D2s_v3")
    .setVirtualMachineConfiguration(
        new VirtualMachineConfiguration(
            new BatchVmImageReference()
                .setPublisher("Canonical")
                .setOffer("0001-com-ubuntu-server-jammy")
                .setSku("22_04-lts")
                .setVersion("latest"),
            "batch.node.ubuntu 22.04"))
    .setTargetDedicatedNodes(2)
    .setStartTask(new StartTask("apt-get update && apt-get install -y python3")
        .setUserIdentity(new UserIdentity()
            .setAutoUser(new AutoUserSpecification()
                .setScope(AutoUserScope.POOL)
                .setElevationLevel(ElevationLevel.ADMIN)))
        .setMaxTaskRetryCount(2)
        .setWaitForSuccess(true)), null);
Create Pool with Application Packages
import java.util.Arrays;

batchClient.createPool(new BatchPoolCreateParameters("appPackagePool", "STANDARD_D2s_v3")
    .setVirtualMachineConfiguration(
        new VirtualMachineConfiguration(
            new BatchVmImageReference()
                .setPublisher("MicrosoftWindowsServer")
                .setOffer("WindowsServer")
                .setSku("2022-datacenter")
                .setVersion("latest"),
            "batch.node.windows amd64"))
    .setTargetDedicatedNodes(2)
    .setApplicationPackageReferences(Arrays.asList(
        new ApplicationPackageReference("myApp").setVersion("1.0"),
        new ApplicationPackageReference("myDependency").setVersion("2.0"))), null);
Get Pool
BatchPool pool = batchClient.getPool("myPoolId");

System.out.println("=== Pool Details ===");
System.out.println("Pool ID: " + pool.getId());
System.out.println("State: " + pool.getState());
System.out.println("Allocation State: " + pool.getAllocationState());
System.out.println("VM Size: " + pool.getVmSize());
System.out.println("Current Dedicated Nodes: " + pool.getCurrentDedicatedNodes());
System.out.println("Current Low Priority Nodes: " + pool.getCurrentLowPriorityNodes());
System.out.println("Target Dedicated Nodes: " + pool.getTargetDedicatedNodes());
List Pools
import com.azure.core.http.rest.PagedIterable;

PagedIterable<BatchPool> pools = batchClient.listPools();

System.out.println("=== Available Pools ===");
for (BatchPool p : pools) {
    System.out.printf("Pool: %s, State: %s, Nodes: %d/%d%n",
        p.getId(),
        p.getState(),
        p.getCurrentDedicatedNodes(),
        p.getTargetDedicatedNodes());
}
Resize Pool
import com.azure.core.util.polling.SyncPoller;
import java.time.Duration;

BatchPoolResizeParameters resizeParams = new BatchPoolResizeParameters()
    .setTargetDedicatedNodes(4)
    .setTargetLowPriorityNodes(2)
    .setResizeTimeout(Duration.ofMinutes(15))
    .setNodeDeallocationOption(BatchNodeDeallocationOption.TASK_COMPLETION);

SyncPoller<BatchPool, BatchPool> poller = batchClient.beginResizePool("myPoolId", resizeParams);
poller.waitForCompletion();

BatchPool resizedPool = poller.getFinalResult();
System.out.println("Pool resized. New target: " + resizedPool.getTargetDedicatedNodes());
Enable AutoScale
String autoScaleFormula = """
    // Target 1 dedicated node per 5 pending tasks
    pendingTasks = $PendingTasks.GetSample(TimeInterval_Minute * 5);
    $TargetDedicatedNodes = min(10, max(1, pendingTasks / 5));
    $TargetLowPriorityNodes = 0;
    """;

BatchPoolEnableAutoScaleParameters autoScaleParams = new BatchPoolEnableAutoScaleParameters()
    .setAutoScaleEvaluationInterval(Duration.ofMinutes(5))
    .setAutoScaleFormula(autoScaleFormula);

batchClient.enablePoolAutoScale("myPoolId", autoScaleParams);
System.out.println("AutoScale enabled");
Disable AutoScale
batchClient.disablePoolAutoScale("myPoolId");
System.out.println("AutoScale disabled");
Delete Pool
SyncPoller<BatchPool, Void> deletePoller = batchClient.beginDeletePool("myPoolId");
deletePoller.waitForCompletion();
System.out.println("Pool deleted");

Job Operations

Create Job
batchClient.createJob(
    new BatchJobCreateParameters("myJobId", new BatchPoolInfo().setPoolId("myPoolId"))
        .setDisplayName("My Batch Job")
        .setPriority(100)
        .setConstraints(new BatchJobConstraints()
            .setMaxWallClockTime(Duration.ofHours(24))
            .setMaxTaskRetryCount(3))
        .setOnAllTasksComplete(OnAllBatchTasksComplete.TERMINATE_JOB)
        .setOnTaskFailure(OnBatchTaskFailure.NO_ACTION),
    null);

System.out.println("Job created: myJobId");
Create Job with Job Manager Task
batchClient.createJob(
    new BatchJobCreateParameters("managedJobId", new BatchPoolInfo().setPoolId("myPoolId"))
        .setJobManagerTask(new BatchJobManagerTask("manager", "python3 manage_tasks.py")
            .setDisplayName("Job Manager")
            .setKillJobOnCompletion(true)
            .setRunExclusive(true)),
    null);
Get Job
BatchJob job = batchClient.getJob("myJobId", null, null);

System.out.println("=== Job Details ===");
System.out.println("Job ID: " + job.getId());
System.out.println("State: " + job.getState());
System.out.println("Priority: " + job.getPriority());
System.out.println("Pool: " + job.getPoolInfo().getPoolId());
System.out.println("Created: " + job.getCreationTime());
List Jobs
PagedIterable<BatchJob> jobs = batchClient.listJobs(new BatchJobsListOptions());

System.out.println("=== Active Jobs ===");
for (BatchJob j : jobs) {
    System.out.printf("Job: %s, State: %s, Pool: %s%n",
        j.getId(),
        j.getState(),
        j.getPoolInfo().getPoolId());
}
Get Task Counts
BatchTaskCountsResult counts = batchClient.getJobTaskCounts("myJobId");

System.out.println("=== Task Counts ===");
System.out.println("Active: " + counts.getTaskCounts().getActive());
System.out.println("Running: " + counts.getTaskCounts().getRunning());
System.out.println("Completed: " + counts.getTaskCounts().getCompleted());
System.out.println("Succeeded: " + counts.getTaskCounts().getSucceeded());
System.out.println("Failed: " + counts.getTaskCounts().getFailed());
Update Job
BatchJobUpdateParameters updateParams = new BatchJobUpdateParameters()
    .setPriority(200)
    .setConstraints(new BatchJobConstraints()
        .setMaxWallClockTime(Duration.ofHours(48)));

batchClient.updateJob("myJobId", updateParams);
System.out.println("Job updated");
Terminate Job
BatchJobTerminateParameters terminateParams = new BatchJobTerminateParameters()
    .setTerminationReason("Manual termination - job complete");
BatchJobTerminateOptions options = new BatchJobTerminateOptions().setParameters(terminateParams);

SyncPoller<BatchJob, BatchJob> poller = batchClient.beginTerminateJob("myJobId", options, null);
poller.waitForCompletion();
System.out.println("Job terminated");
Delete Job
SyncPoller<BatchJob, Void> deletePoller = batchClient.beginDeleteJob("myJobId");
deletePoller.waitForCompletion();
System.out.println("Job deleted");

Task Operations

Create Single Task
BatchTaskCreateParameters task = new BatchTaskCreateParameters("task1", "echo 'Hello World'");
batchClient.createTask("myJobId", task);
System.out.println("Task created: task1");
Create Task with Resource Files
import java.util.Arrays;

BatchTaskCreateParameters task = new BatchTaskCreateParameters("processDataTask", 
    "python3 process.py input.csv output.csv")
    .setResourceFiles(Arrays.asList(
        new ResourceFile()
            .setHttpUrl("https://storage.blob.core.windows.net/container/process.py?sasToken")
            .setFilePath("process.py"),
        new ResourceFile()
            .setHttpUrl("https://storage.blob.core.windows.net/container/input.csv?sasToken")
            .setFilePath("input.csv")))
    .setOutputFiles(Arrays.asList(
        new OutputFile("output.csv")
            .setDestination(new OutputFileDestination()
                .setContainer(new OutputFileBlobContainerDestination(
                    "https://storage.blob.core.windows.net/results?sasToken")
                    .setPath("results/output.csv")))
            .setUploadOptions(new OutputFileUploadOptions()
                .setUploadCondition(OutputFileUploadCondition.TASK_SUCCESS))));

batchClient.createTask("myJobId", task);
Create Task with Exit Conditions
BatchTaskCreateParameters task = new BatchTaskCreateParameters("conditionalTask", "cmd /c exit 3")
    .setExitConditions(new ExitConditions()
        .setExitCodeRanges(Arrays.asList(
            new ExitCodeRangeMapping(0, 0,
                new ExitOptions().setJobAction(BatchJobActionKind.NONE)),
            new ExitCodeRangeMapping(1, 5,
                new ExitOptions().setJobAction(BatchJobActionKind.TERMINATE)),
            new ExitCodeRangeMapping(6, 10,
                new ExitOptions().setDependencyAction(DependencyActionKind.BLOCK))))
        .setDefault(new ExitOptions()
            .setJobAction(BatchJobActionKind.NONE)));

batchClient.createTask("myJobId", task);
Create Task with User Identity
BatchTaskCreateParameters task = new BatchTaskCreateParameters("adminTask", "sudo apt-get update")
    .setUserIdentity(new UserIdentity()
        .setAutoUser(new AutoUserSpecification()
            .setScope(AutoUserScope.TASK)
            .setElevationLevel(ElevationLevel.ADMIN)));

batchClient.createTask("myJobId", task);
Create Task Collection (up to 100)
List<BatchTaskCreateParameters> taskList = Arrays.asList(
    new BatchTaskCreateParameters("task1", "echo Task 1"),
    new BatchTaskCreateParameters("task2", "echo Task 2"),
    new BatchTaskCreateParameters("task3", "echo Task 3"),
    new BatchTaskCreateParameters("task4", "echo Task 4"),
    new BatchTaskCreateParameters("task5", "echo Task 5")
);

BatchTaskGroup taskGroup = new BatchTaskGroup(taskList);
BatchCreateTaskCollectionResult result = batchClient.createTaskCollection("myJobId", taskGroup);

System.out.printf("Created %d tasks%n", result.getValue().size());
Create Many Tasks (no limit)
import java.util.ArrayList;

List<BatchTaskCreateParameters> tasks = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
    tasks.add(new BatchTaskCreateParameters("task" + i, 
        String.format("python3 process.py --partition %d", i)));
}

batchClient.createTasks("myJobId", tasks);
System.out.printf("Created %d tasks%n", tasks.size());
Create Task with Dependencies
// First, create prerequisite tasks
batchClient.createTask("myJobId", new BatchTaskCreateParameters("setup", "setup.sh"));
batchClient.createTask("myJobId", new BatchTaskCreateParameters("download", "download.sh"));

// Create dependent task
BatchTaskCreateParameters dependentTask = new BatchTaskCreateParameters("process", "process.sh")
    .setDependsOn(new BatchTaskDependencies()
        .setTaskIds(Arrays.asList("setup", "download")));

batchClient.createTask("myJobId", dependentTask);
Get Task
BatchTask task = batchClient.getTask("myJobId", "task1");

System.out.println("=== Task Details ===");
System.out.println("Task ID: " + task.getId());
System.out.println("State: " + task.getState());
System.out.println("Command: " + task.getCommandLine());

if (task.getExecutionInfo() != null) {
    System.out.println("Exit Code: " + task.getExecutionInfo().getExitCode());
    System.out.println("Start Time: " + task.getExecutionInfo().getStartTime());
    System.out.println("End Time: " + task.getExecutionInfo().getEndTime());
    
    if (task.getExecutionInfo().getFailureInfo() != null) {
        System.out.println("Failure: " + task.getExecutionInfo().getFailureInfo().getMessage());
    }
}
List Tasks
PagedIterable<BatchTask> tasks = batchClient.listTasks("myJobId");

System.out.println("=== Tasks ===");
for (BatchTask t : tasks) {
    System.out.printf("Task: %s, State: %s%n", t.getId(), t.getState());
}
Get Task Output
import com.azure.core.util.BinaryData;
import java.nio.charset.StandardCharsets;

// Get stdout
BinaryData stdout = batchClient.getTaskFile("myJobId", "task1", "stdout.txt");
System.out.println("=== stdout ===");
System.out.println(new String(stdout.toBytes(), StandardCharsets.UTF_8));

// Get stderr
BinaryData stderr = batchClient.getTaskFile("myJobId", "task1", "stderr.txt");
System.out.println("=== stderr ===");
System.out.println(new String(stderr.toBytes(), StandardCharsets.UTF_8));
List Task Files
PagedIterable<BatchNodeFile> files = batchClient.listTaskFiles("myJobId", "task1");

System.out.println("=== Task Files ===");
for (BatchNodeFile file : files) {
    System.out.printf("File: %s, Size: %d bytes%n",
        file.getName(),
        file.getProperties().getContentLength());
}
Terminate Task
batchClient.terminateTask("myJobId", "task1", null, null);
System.out.println("Task terminated");
Delete Task
batchClient.deleteTask("myJobId", "task1");
System.out.println("Task deleted");

Node Operations

List Nodes
PagedIterable<BatchNode> nodes = batchClient.listNodes("myPoolId", new BatchNodesListOptions());

System.out.println("=== Compute Nodes ===");
for (BatchNode node : nodes) {
    System.out.printf("Node: %s, State: %s, IP: %s%n",
        node.getId(),
        node.getState(),
        node.getIpAddress());
}
Get Node
BatchNode node = batchClient.getNode("myPoolId", "nodeId");

System.out.println("=== Node Details ===");
System.out.println("Node ID: " + node.getId());
System.out.println("State: " + node.getState());
System.out.println("IP Address: " + node.getIpAddress());
System.out.println("VM Size: " + node.getVmSize());
System.out.println("Total Tasks Run: " + node.getTotalTasksRun());
System.out.println("Running Tasks: " + node.getRunningTasksCount());
Reboot Node
BatchNodeRebootParameters rebootParams = new BatchNodeRebootParameters()
    .setNodeRebootOption(BatchNodeRebootOption.TASK_COMPLETION);

SyncPoller<BatchNode, BatchNode> rebootPoller = 
    batchClient.beginRebootNode("myPoolId", "nodeId", rebootParams);
rebootPoller.waitForCompletion();
System.out.println("Node rebooted");
Get Remote Login Settings
BatchNodeRemoteLoginSettings settings = batchClient.getNodeRemoteLoginSettings("myPoolId", "nodeId");

System.out.println("=== Remote Login Settings ===");
System.out.println("IP Address: " + settings.getRemoteLoginIpAddress());
System.out.println("Port: " + settings.getRemoteLoginPort());

// SSH command
System.out.printf("SSH: ssh -p %d user@%s%n",
    settings.getRemoteLoginPort(),
    settings.getRemoteLoginIpAddress());
Remove Node from Pool
BatchNodeRemoveParameters removeParams = new BatchNodeRemoveParameters(
    Arrays.asList("nodeId1", "nodeId2"))
    .setNodeDeallocationOption(BatchNodeDeallocationOption.TASK_COMPLETION)
    .setResizeTimeout(Duration.ofMinutes(15));

batchClient.removeNodes("myPoolId", removeParams);
System.out.println("Nodes removal initiated");

Job Schedule Operations

Create Job Schedule
import java.time.OffsetDateTime;

batchClient.createJobSchedule(new BatchJobScheduleCreateParameters("dailySchedule",
    new BatchJobScheduleConfiguration()
        .setRecurrenceInterval(Duration.ofHours(24))
        .setDoNotRunUntil(OffsetDateTime.now().plusHours(1))
        .setDoNotRunAfter(OffsetDateTime.now().plusDays(30)),
    new BatchJobSpecification(new BatchPoolInfo().setPoolId("myPoolId"))
        .setDisplayName("Daily Processing Job")
        .setPriority(100)
        .setConstraints(new BatchJobConstraints()
            .setMaxTaskRetryCount(3))),
    null);

System.out.println("Job schedule created: dailySchedule");
Get Job Schedule
BatchJobSchedule schedule = batchClient.getJobSchedule("dailySchedule");

System.out.println("=== Job Schedule Details ===");
System.out.println("Schedule ID: " + schedule.getId());
System.out.println("State: " + schedule.getState());
System.out.println("Next Run: " + schedule.getExecutionInfo().getNextRunTime());
System.out.println("Recent Jobs: " + schedule.getExecutionInfo().getRecentJob());
List Job Schedules
PagedIterable<BatchJobSchedule> schedules = batchClient.listJobSchedules();

System.out.println("=== Job Schedules ===");
for (BatchJobSchedule s : schedules) {
    System.out.printf("Schedule: %s, State: %s%n", s.getId(), s.getState());
}
Disable Job Schedule
batchClient.disableJobSchedule("dailySchedule");
System.out.println("Job schedule disabled");
Enable Job Schedule
batchClient.enableJobSchedule("dailySchedule");
System.out.println("Job schedule enabled");
Terminate Job Schedule
batchClient.terminateJobSchedule("dailySchedule");
System.out.println("Job schedule terminated");
Delete Job Schedule
batchClient.deleteJobSchedule("dailySchedule");
System.out.println("Job schedule deleted");

Error Handling

import com.azure.compute.batch.models.BatchErrorException;
import com.azure.compute.batch.models.BatchError;

try {
    BatchPool pool = batchClient.getPool("nonexistent-pool");
} catch (BatchErrorException e) {
    BatchError error = e.getValue();
    
    System.err.println("=== Batch Error ===");
    System.err.println("Error code: " + error.getCode());
    System.err.println("Message: " + error.getMessage().getValue());
    
    // Handle specific errors
    switch (error.getCode()) {
        case "PoolNotFound":
            System.err.println("The specified pool does not exist.");
            break;
        case "JobNotFound":
            System.err.println("The specified job does not exist.");
            break;
        case "TaskNotFound":
            System.err.println("The specified task does not exist.");
            break;
        case "PoolQuotaReached":
            System.err.println("Pool quota exceeded. Delete unused pools or request quota increase.");
            break;
        case "ActiveJobAndScheduleQuotaReached":
            System.err.println("Job quota exceeded.");
            break;
        default:
            System.err.println("Unexpected error: " + error.getCode());
    }
    
    // Show additional details if available
    if (error.getValues() != null) {
        for (var detail : error.getValues()) {
            System.err.printf("  %s: %s%n", detail.getKey(), detail.getValue());
        }
    }
}

Complete Application Example

import com.azure.compute.batch.BatchClient;
import com.azure.compute.batch.BatchClientBuilder;
import com.azure.compute.batch.models.*;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.util.BinaryData;
import com.azure.identity.DefaultAzureCredentialBuilder;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;

public class BatchJobRunner {
    
    private final BatchClient client;
    private final String poolId;
    
    public BatchJobRunner(String poolId) {
        this.client = new BatchClientBuilder()
            .endpoint(System.getenv("AZURE_BATCH_ENDPOINT"))
            .credential(new DefaultAzureCredentialBuilder().build())
            .buildClient();
        this.poolId = poolId;
    }
    
    public void ensurePoolExists() {
        try {
            BatchPool pool = client.getPool(poolId);
            System.out.println("Pool exists: " + pool.getId());
        } catch (BatchErrorException e) {
            if ("PoolNotFound".equals(e.getValue().getCode())) {
                createPool();
            } else {
                throw e;
            }
        }
    }
    
    private void createPool() {
        System.out.println("Creating pool: " + poolId);
        
        client.createPool(new BatchPoolCreateParameters(poolId, "STANDARD_D2s_v3")
            .setVirtualMachineConfiguration(
                new VirtualMachineConfiguration(
                    new BatchVmImageReference()
                        .setPublisher("Canonical")
                        .setOffer("0001-com-ubuntu-server-jammy")
                        .setSku("22_04-lts")
                        .setVersion("latest"),
                    "batch.node.ubuntu 22.04"))
            .setTargetDedicatedNodes(2)
            .setTaskSlotsPerNode(4), null);
        
        // Wait for pool to be ready
        waitForPoolReady();
    }
    
    private void waitForPoolReady() {
        System.out.println("Waiting for pool to be ready...");
        while (true) {
            BatchPool pool = client.getPool(poolId);
            if (pool.getAllocationState() == AllocationState.STEADY 
                && pool.getCurrentDedicatedNodes() > 0) {
                System.out.println("Pool is ready with " + pool.getCurrentDedicatedNodes() + " nodes");
                break;
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }
    }
    
    public String runJob(String jobId, List<String> commands) {
        // Create job
        client.createJob(
            new BatchJobCreateParameters(jobId, new BatchPoolInfo().setPoolId(poolId))
                .setOnAllTasksComplete(OnAllBatchTasksComplete.TERMINATE_JOB),
            null);
        
        System.out.println("Job created: " + jobId);
        
        // Create tasks
        List<BatchTaskCreateParameters> tasks = new ArrayList<>();
        for (int i = 0; i < commands.size(); i++) {
            tasks.add(new BatchTaskCreateParameters("task" + i, commands.get(i)));
        }
        
        client.createTasks(jobId, tasks);
        System.out.println("Created " + tasks.size() + " tasks");
        
        // Wait for completion
        waitForJobComplete(jobId);
        
        return jobId;
    }
    
    private void waitForJobComplete(String jobId) {
        System.out.println("Waiting for job to complete...");
        while (true) {
            BatchJob job = client.getJob(jobId, null, null);
            
            if (job.getState() == BatchJobState.COMPLETED) {
                System.out.println("Job completed");
                break;
            } else if (job.getState() == BatchJobState.DISABLED 
                    || job.getState() == BatchJobState.TERMINATING) {
                throw new RuntimeException("Job failed or was terminated");
            }
            
            // Show progress
            BatchTaskCountsResult counts = client.getJobTaskCounts(jobId);
            System.out.printf("Progress: %d/%d tasks completed%n",
                counts.getTaskCounts().getCompleted(),
                counts.getTaskCounts().getActive() + counts.getTaskCounts().getRunning() 
                    + counts.getTaskCounts().getCompleted());
            
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }
    }
    
    public Map<String, String> getTaskOutputs(String jobId) {
        Map<String, String> outputs = new HashMap<>();
        
        PagedIterable<BatchTask> tasks = client.listTasks(jobId);
        for (BatchTask task : tasks) {
            try {
                BinaryData stdout = client.getTaskFile(jobId, task.getId(), "stdout.txt");
                outputs.put(task.getId(), new String(stdout.toBytes(), StandardCharsets.UTF_8));
            } catch (Exception e) {
                outputs.put(task.getId(), "Error: " + e.getMessage());
            }
        }
        
        return outputs;
    }
    
    public void cleanup(String jobId) {
        try {
            client.beginDeleteJob(jobId).waitForCompletion();
            System.out.println("Job deleted: " + jobId);
        } catch (Exception e) {
            System.err.println("Failed to delete job: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        BatchJobRunner runner = new BatchJobRunner("my-batch-pool");
        
        try {
            // Ensure pool exists
            runner.ensurePoolExists();
            
            // Run job with tasks
            List<String> commands = Arrays.asList(
                "echo 'Processing partition 1' && sleep 5",
                "echo 'Processing partition 2' && sleep 5",
                "echo 'Processing partition 3' && sleep 5",
                "echo 'Processing partition 4' && sleep 5"
            );
            
            String jobId = "job-" + System.currentTimeMillis();
            runner.runJob(jobId, commands);
            
            // Get outputs
            Map<String, String> outputs = runner.getTaskOutputs(jobId);
            
            System.out.println("\n=== Task Outputs ===");
            outputs.forEach((taskId, output) -> {
                System.out.printf("%s: %s%n", taskId, output.trim());
            });
            
            // Cleanup
            runner.cleanup(jobId);
            
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Environment Variables

AZURE_BATCH_ENDPOINT=https://<account>.<region>.batch.azure.com
AZURE_BATCH_ACCOUNT=<account-name>
AZURE_BATCH_ACCESS_KEY=<account-key>

# For DefaultAzureCredential
AZURE_CLIENT_ID=<service-principal-client-id>
AZURE_CLIENT_SECRET=<service-principal-secret>
AZURE_TENANT_ID=<tenant-id>

Best Practices

  1. Use Entra ID — Preferred over shared key for authentication

  2. Use management SDK for pools — azure-resourcemanager-batch supports managed identities

  3. Batch task creation — Use createTaskCollection or createTasks for multiple tasks

  4. Handle LRO properly — Pool resize, delete operations are long-running

  5. Monitor task counts — Use getJobTaskCounts to track progress

  6. Set constraints — Configure maxWallClockTime and maxTaskRetryCount

  7. Use low-priority nodes — Cost savings for fault-tolerant workloads

  8. Enable autoscale — Dynamically adjust pool size based on workload

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Microsoft
Publisher
Microsoft (Official)
Source
microsoft/skills · .github/plugins/azure-sdk-java/skills/azure-compute-batch-java · commit 0696600
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Microsoft.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-compute-batch-java.zip