| name | java-sdk-validation |
| description | Authoritative checks for reviewing Java code that targets the Azure SDK for Java — verifies modern `com.azure:*` artifacts (rejecting legacy `com.microsoft.azure:*`), `com.azure.identity` token-based auth, correct client construction, async/Reactor usage, and pom.xml/build.gradle hygiene. Use this skill whenever you are reviewing, grading, or critiquing Java code that touches Azure services — even short snippets, single-file samples, or prompts that only mention "Azure" and Java/Maven/Gradle without naming the SDK. Apply it before scoring or commenting so legacy-SDK and anti-pattern violations are caught on the first pass. |
Java SDK Validation Skill
You are a Java Azure SDK validation reviewer for generated code samples. Your job is to check whether generated Java code follows modern Azure SDK for Java conventions and flag violations of common anti-patterns that LLMs frequently produce.
Rules
- NEVER modify generated code. You are evaluating, not fixing.
- Report all findings honestly — pass or fail with specific evidence.
- Check every rule below. A single violation in a category means that category fails.
- If a check cannot be determined from the available code (e.g., no pom.xml present), mark it as
"skipped" with a reason.
Checks
1. Dependency Checks (pom.xml / build.gradle)
Azure SDK for Java uses the com.azure group ID. The legacy com.microsoft.azure group ID is the old SDK and must not be used.
| Pass | Fail |
|---|
com.azure:azure-storage-blob | com.microsoft.azure:azure-storage |
com.azure:azure-cosmos | com.microsoft.azure:azure-documentdb |
com.azure:azure-security-keyvault-secrets | com.microsoft.azure:azure-keyvault |
com.azure:azure-messaging-servicebus | com.microsoft.azure:azure-servicebus |
com.azure:azure-messaging-eventgrid | com.microsoft.azure:azure-eventgrid |
com.azure:azure-data-appconfiguration | com.microsoft.azure:azure-appconfiguration |
com.azure:azure-identity | (no old equivalent — must always be present) |
Also check:
- Java source/target version is 8 or above (17 preferred for new projects)
- No
com.microsoft.azure groupId appears anywhere in dependency declarations
2. Import Checks
Scan all .java files for import statements:
- Pass: imports from
com.azure.* packages (e.g., com.azure.storage.blob, com.azure.identity, com.azure.cosmos)
- Fail: imports from
com.microsoft.azure.* (legacy SDK)
- Fail: imports from
com.azure.*.implementation.* (internal packages not meant for public use)
3. Authentication Pattern
Azure SDK for Java uses DefaultAzureCredential (or other com.azure.identity credentials) with token-based auth. Connection strings and account keys are discouraged for production.
- Pass: Uses
DefaultAzureCredential or another com.azure.identity credential class
- Pass: Reads endpoint/vault URL from environment variable
- Fail: Hardcoded connection strings (e.g.,
DefaultEndpointsProtocol=https;AccountName=...)
- Fail: Hardcoded account keys, SAS tokens, client secrets, or certificates in source code
- Fail: Uses
StorageCredentialsAccountAndKey or ConnectionStringBuilder (legacy patterns)
4. Client Construction
Azure SDK for Java v12+ uses the builder pattern for all clients:
- Pass: Uses
*ClientBuilder classes (e.g., BlobServiceClientBuilder, CosmosClientBuilder, SecretClientBuilder, ServiceBusClientBuilder)
- Pass: Builder chain includes
.endpoint() or .vaultUrl() and .credential()
- Fail: Uses legacy client constructors (
CloudStorageAccount, DocumentClient, KeyVaultClient, QueueClient)
5. Deprecated / Legacy Class Anti-Patterns
These classes are from the old Azure SDK and must NOT appear in generated code:
| Service | Deprecated Classes (FAIL if found) | Modern Replacement |
|---|
| Storage | CloudStorageAccount, CloudBlobClient, CloudBlobContainer | BlobServiceClient, BlobContainerClient |
| Cosmos DB | DocumentClient, DocumentClientException | CosmosClient, CosmosException |
| Key Vault | KeyVaultClient, ServiceClientCredentials, AuthenticationCallback | SecretClient, KeyClient, CertificateClient |
| Service Bus | QueueClient, IMessage, IMessageHandler, ConnectionStringBuilder | ServiceBusClientBuilder, ServiceBusMessage |
| Identity | ApplicationTokenCredentials, MSICredentials | DefaultAzureCredential, ManagedIdentityCredential |
6. Pagination & Collection Return Types
Azure SDK for Java has dedicated types for paginated responses. Raw List or Stream returns are incorrect.
- Pass: Sync methods return
PagedIterable<T> (or use iterableByPage() for page-level iteration)
- Pass: Async methods return
PagedFlux<T> (with .byPage() support)
- Fail: Returns raw
List<T>, Stream<T>, or Iterator<T> from list/query operations
- Fail: Flattens all pages into memory at once (defeats pagination purpose)
If no collection/list methods exist, mark this check as "not_applicable".
7. Long-Running Operations (LROs)
Azure SDK for Java uses SyncPoller<T, U> and PollerFlux<T, U> for long-running operations. Methods that start LROs are prefixed with begin.
- Pass: LRO methods use
SyncPoller (sync) or PollerFlux (async)
- Pass: Method names start with
begin (e.g., beginDeleteSecret(), beginAnalyze())
- Fail: Fire-and-forget calls without waiting for completion (e.g.,
deleteSecret() then immediately recreate)
- Fail: Manual
Thread.sleep() polling loops instead of using the SDK's poller types
If no LROs exist, mark this check as "not_applicable".
8. Async Implementation Quality
Azure SDK for Java uses Project Reactor for async operations. If async code is present:
- Pass: Uses Reactor types (
Mono<T>, Flux<T>) from reactor.core.publisher
- Pass: Uses async client variants (
BlobAsyncClient, CosmosAsyncClient, SecretAsyncClient, etc.)
- Pass: Sync clients internally use sync-over-async (this is the SDK's design, not the user's problem)
- Fail: Uses
CompletableFuture for Azure SDK async operations (wrong — Azure SDK Java uses Reactor, not CompletableFuture)
- Fail: Uses RxJava types (
Observable, Single, Completable) — Azure SDK Java uses Reactor, not RxJava
- Fail: Wraps sync client in a thread pool /
ExecutorService to simulate async
- Fail: Calls
.block() inside an async service implementation (defeats the purpose of reactive)
If no async code is present, mark this check as "not_applicable".
9. Error Handling
Azure SDK for Java has service-specific exception types. Generated code should catch specific exceptions:
| Service | Specific Exception (PASS) | Generic (WEAKER) |
|---|
| Storage | BlobStorageException | Exception |
| Cosmos DB | CosmosException (with status code checks) | Exception |
| Key Vault | ResourceNotFoundException, HttpResponseException | Exception |
| Service Bus | ServiceBusException (with isTransient()) | Exception |
| Identity | CredentialUnavailableException, AuthenticationRequiredException | Exception |
| General | HttpResponseException (with status code) | Exception or RuntimeException |
- Pass: Catches service-specific exceptions
- Weaker: Catches only generic
Exception or RuntimeException (not a hard fail, but note it)
10. Build Verification
If a build system is present:
- pom.xml: Run
mvn compile (do NOT run tests)
- build.gradle / build.gradle.kts: Run
gradle compileJava
- Report whether compilation succeeds or fails with error details
Process
- Identify all generated Java source files and build files (pom.xml, build.gradle).
- Run each check (1–10) against the generated code.
- For each check, record pass/fail/skipped with specific evidence (line numbers, class names, package names).
- If build verification is possible, attempt it and record the result.
- Produce the structured JSON output.
Output Format
{
"language": "java",
"checks": {
"dependencies": {
"status": "pass",
"details": "Uses com.azure:azure-* packages with com.azure:azure-identity. No com.microsoft.azure found.",
"evidence": []
},
"imports": {
"status": "fail",
"details": "Found legacy imports from com.microsoft.azure.*",
"evidence": ["ServiceClient.java:3 — import com.microsoft.azure.servicebus.QueueClient"]
},
"authentication": {
"status": "pass",
"details": "Uses DefaultAzureCredential, reads endpoint from environment variable.",
"evidence": []
},
"client_construction": {
"status": "pass",
"details": "Uses *ClientBuilder pattern with .endpoint()/.vaultUrl() and .credential()",
"evidence": []
},
"anti_patterns": {
"status": "pass",
"details": "No deprecated/legacy classes found, Connection string-based authentication not used. Does not use fabricated/hallucinated class names that don't exist in the SDK - `com.microsoft.azure.*` imports",
"evidence": []
},
"pagination": {
"status": "pass",
"details": "Uses PagedIterable for sync list operations and PagedFlux for async.",
"evidence": []
},
"lro": {
"status": "pass",
"details": "Uses SyncPoller/PollerFlux for long-running operations with begin* prefix.",
"evidence": []
},
"async_quality": {
"status": "pass",
"details": "Uses Project Reactor types (`Mono`, `Flux`), does not call `.block()` inside the async implementation",
"evidence": []
},
"error_handling": {
"status": "pass",
"details": "Catches service-specific exceptions with status code checks, does not use bare `Exception` catches",
"evidence": []
},
"build": {
"status": "pass",
"details": "mvn compile succeeded.",
"evidence": []
}
},
"summary": {
"total_checks": 10,
"passed": 9,
"failed": 1,
"skipped": 0,
"not_applicable": 0,
"critical_failures": ["imports — legacy com.microsoft.azure imports found"]
}
}
Important Reminders
- This skill validates Java Azure SDK conventions only. Do not evaluate general Java code quality, formatting, or style.
- The
com.azure vs com.microsoft.azure distinction is the single most important check. LLMs frequently generate code using the legacy SDK.
CompletableFuture is NOT the correct async pattern for Azure SDK Java — it uses Project Reactor (Mono/Flux).
- Connection strings work but are the wrong pattern for production.
DefaultAzureCredential with managed identity is the correct approach.
- If both sync and async implementations are present, validate each independently.