Skip to content

feat: add Java client for the Apify API (spec v2-2026-07-02T131926Z)#1

Merged
Pijukatel merged 12 commits into
masterfrom
claude/vigilant-goodall-7s05ro
Jul 5, 2026
Merged

feat: add Java client for the Apify API (spec v2-2026-07-02T131926Z)#1
Pijukatel merged 12 commits into
masterfrom
claude/vigilant-goodall-7s05ro

Conversation

@Pijukatel

@Pijukatel Pijukatel commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the official (experimental, AI-generated and AI-maintained) Java client for the Apify API, built from scratch and verified against OpenAPI specification v2-2026-07-01T115402Z. The public interface mirrors the JavaScript reference client (apify-client-js) and is consistent with the existing Rust/Go siblings.

What's included

  • Resource-oriented ApifyClient with accessors for Actors (+ versions & env vars), builds, runs, datasets, key-value stores, request queues, tasks, schedules, webhooks, webhook dispatches, the Apify Store, users, and logs, plus setStatusMessage.
  • Replaceable HTTP transport via the HttpBackend interface (default DefaultHttpBackend over the JDK java.net.http.HttpClient).
  • Cross-cutting behaviour on every call: bearer auth, the mandated User-Agent, exponential-backoff-with-jitter retries (429/5xx/network), and a growing-but-capped per-attempt timeout.
  • Convenience helpers matching the reference client: actor(...).call/task(...).call, waitForFinish, defaultBuild, metamorph/reboot/resurrect/charge, run-nested storages, validateInput, lazy store().iterate() and requestQueue(...).paginateRequests(), dataset download/statistics/public URLs, key-value-store record & key-list public URLs with HMAC-SHA256 signing, request-queue lock lifecycle, and batchAddRequests with unprocessed-request retry.
  • Public version constants Version.CLIENT_VERSION and Version.API_SPEC_VERSION; forward-compatible models with an extra map for unmodelled fields.

Tests, docs & CI

  • Offline unit tests (mock backend: retries, error parsing, 404→empty, User-Agent, base-URL resolution, signature known-answer tests) and a live integration suite (one simple GET + one CRUD/complex flow per resource).
  • 7 runnable example programs with a CI harness that executes them, plus a doc-snippet compile test.
  • docs/ reference for every resource, CHANGELOG.md, and README with setup/usage.
  • Quality gates: Spotless (google-java-format) + SpotBugs static analysis + javac -Xlint.
  • GitHub Actions: Java integration tests (path-filtered PR-to-master + manual dispatch, standalone Test examples step) and a manual Publish Java client workflow to Maven Central via the Sonatype Central Portal with a tagged GitHub release; all secrets from repo secrets.

Verification

  • mvn spotless:check — clean
  • mvn spotbugs:check — 0 bugs
  • mvn test92 tests, 0 failures/errors/skips (offline unit + live integration with APIFY_TOKEN + 7 example programs + doc snippets)

Scope notes

  • Endpoint scope tracks the JS reference; for in-scope endpoints all OpenAPI parameters are covered (e.g. store allowsAgenticUsers/responseFormat, monthlyUsage(date)).
  • Nested actor/task webhooks() are read-only, matching the spec (those nested endpoints are GET-only).

Generated by Claude Code

claude and others added 3 commits July 3, 2026 10:24
Bespoke, idiomatic Java client mirroring the reference JS client:
resource clients for actors, builds, runs, datasets, key-value stores,
request queues, tasks, schedules, webhooks, dispatches, store, users and
logs, plus setStatusMessage. Replaceable HTTP transport (HttpBackend),
bearer auth, mandated User-Agent, exponential-backoff retries with jitter,
Optional-based 404 handling, and byte-for-byte storage URL signing.

Includes offline unit tests, live integration tests (one GET + one CRUD
flow per resource), 7 runnable example programs, doc-snippet compile test,
docs/, CHANGELOG, Spotless + SpotBugs gates, and CI workflows for
integration tests and Maven Central publishing (OIDC Trusted Publisher).
Restore validateInput(input[, ValidateInputOptions]) — present in both the
OpenAPI spec (POST /v2/actors/{actorId}/validate-input) and the JS reference
client. Parses the bare {"valid": <bool>} response (no data envelope) via a
new no-envelope POST helper. Adds a live integration test.
- Bump API_SPEC_VERSION to v2-2026-07-02T131926Z (version-only spec sync;
  in-scope typed surface unchanged, validateInput confirmed in JS reference scope).
- Publishing workflow: use GitHub environment `Publishing` with the mandated
  Maven Central secret names + credential fail-fast guard.
- Review fixes: single-source per-attempt request timeout, batchAddRequests
  rethrows non-retryable 4xx, store iterator handles empty/short pages,
  getOrCreate(name, schema) overloads, propagate last-run status/origin to
  nested storage/log accessors, CI failIfNoTests, docs and CHANGELOG fixes,
  and additional offline unit tests.
@Pijukatel Pijukatel changed the title feat: add Java client for the Apify API (spec v2-2026-07-01T115402Z) feat: add Java client for the Apify API (spec v2-2026-07-02T131926Z) Jul 4, 2026
claude added 9 commits July 4, 2026 20:49
…g test and doc fixes

- DatasetClient.pushItems now applies ctx.mergedParams like every sibling, so a
  last-run-seeded context targets the same run's dataset on write as on read.
- Add a direct GET /v2/logs/{id} assertion (client.log(id)) in BuildIntegrationTest.
- README: state the import package (com.apify.client) and JsonNode/Duration origins.
- docs/storages.md: document the getOrCreate(name, schema) overload for dataset and KVS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
…omment polish

- RunClient.charge and TaskClient.updateInput now apply ctx.mergedParams like their
  siblings, so a seeded context targets the same run/task on write as on read (IT2-1).
- README: import hint now also covers java.util.Optional/Map (IT2-2).
- RequestQueueClient: rephrase batch-retry comment to wrap cleanly (IT2-3).
- RunClient.getWithWait javadoc reworded to match clamp behaviour (IT2-4).
- docs/examples.md: use the storage snippet locals so none are dead (IT2-5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
- ActorClient.defaultBuild clamps waitForFinish via clampServerWait like the twins (IT3-3).
- UserClient.updateLimits routes through mergedParams for call-site uniformity (IT3-2).
- BuildClient.getWithWait javadoc reworded to match RunClient twin (IT3-1).
- docs/storages.md: add storage metadata-model field table; add missing return types (IT3-4/5).
- docs/runs.md: add return types for metamorph and charge (IT3-5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
…nt GetRecordOptions

- IT4-1: the storage public-URL builders match the JS reference (URL = resource path +
  signature over the resolved concrete id + explicit options; seeded status/origin filters
  are not carried). Documented the last-run-nested limitation in docs/storages.md and added
  maintainer comments; no behavioral change (matching the reference is required).
- IT4-2: document GetRecordOptions (attachment, signature) in docs/storages.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
The comment said 'resource path + signature only', but createKeysPublicUrl forwards the
ListKeysOptions filters into the URL; reword to 'resource path + explicit options + signature'
to match the method's Javadoc and the DatasetClient sibling (IT5-1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
… clients

docs/actors.md gave the four version/env-var clients prose only; add Method/Description
tables (matching every other client section) and an ActorVersion field list (IT6-1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
…mits)

docs/storages.md listItems(..., Class<T>) now states Returns PaginationList<T>;
docs/misc.md updateLimits(Object) now states No return value (IT7-1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
Complete the return-type documentation: runs.md/builds.md getWithWait rows now state
Optional<ActorRun>/Optional<Build> and describe the clamp instead of a stale (max 60).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017sJGjCxFP3bpbeF4LsVqK3
The default JDK HttpClient used Redirect.NEVER, so endpoints that answer with
a 302 (e.g. a non-attachment key-value-store record served from external
storage) surfaced as errors instead of being followed, diverging from the
reference clients. Use Redirect.NORMAL (no HTTPS->HTTP downgrade; the JDK
strips Authorization on cross-origin hops, so the token is not leaked).
@Pijukatel Pijukatel merged commit 2b7c069 into master Jul 5, 2026
2 checks passed
@Pijukatel Pijukatel deleted the claude/vigilant-goodall-7s05ro branch July 8, 2026 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants