feat(sdk/java): Spring Boot starter, reactive hardening, examples, live integration#25
Merged
Conversation
…ve integration
Restructures the Java SDK into a 3-module Maven build and ships the
"best" Boot 3.5.9 reactive surface in one pass:
flydocs-sdk (core)
==================
* AutoCloseable on both FlydocsClient and FlydocsClientAsync -- the
Netty ConnectionProvider is owned and disposed on close().
* Opt-in retry filter via Builder.maxAttempts(N) + retryMinBackoff.
Retries transient 5xx + timeouts with exponential backoff; never
retries 4xx (intentional state like 409 job_not_cancellable).
* Builder knobs: maxConnections, pendingAcquireTimeout, maxInMemorySize
-- bounded pool + caller-tunable buffer limits.
* waitForCompletion: replaced the recursive flatMap with
Mono.defer + repeatWhenEmpty + outer timeout -- one timeout
subscriber, no nested chain.
* Cleaned up redundant codec config (was setting maxInMemorySize twice).
flydocs-spring-boot-starter (NEW)
=================================
* FlydocsAutoConfiguration with @autoConfiguration + @ConditionalOnClass
+ @ConditionalOnProperty(prefix="flydocs", name="base-url").
* FlydocsProperties: timeout, max-attempts, retry-min-backoff,
max-connections, pending-acquire-timeout, max-in-memory-size,
tenant-id, webhook.hmac-secret.
* @ConditionalOnMissingBean on every produced bean so users can
override with a custom @bean.
* Bean destroyMethod="close" so the Netty pool is released cleanly
on Spring context shutdown.
* WebhookVerifier bean conditional on flydocs.webhook.hmac-secret.
* spring-boot-configuration-processor for IDE completion in
application.yaml.
* META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
so Spring Boot 3.x discovery picks it up without spring.factories.
* 5 tests using ApplicationContextRunner cover the conditional
wiring, user-bean override, and property binding.
flydocs-examples (NEW; not deployed)
====================================
Six runnable example classes in 1:1 parity with the Python SDK:
FirstExtractionExample (01_first_extraction.py)
TypedSchemaAndRulesExample (02_typed_schema_and_rules.py)
AsyncJobWithWaitExample (03_async_job_with_wait.py)
WebhookReceiverApplication (04_webhook_receiver_fastapi.py)
ErrorHandlingExample (05_error_handling.py)
SyncFacadeExample (06_sync_facade.py)
+ ExampleHelpers fixture mirror of examples_helpers.py.
maven.deploy.skip=true so the module compile-checks but never ships.
Live integration tests
======================
LiveApiIntegrationTest in flydocs-sdk/src/test/.../integration/,
tagged @tag("integration") and gated on FLYDOCS_BASE_URL. Verified
end-to-end against a running service: version, health, validate,
listJobs, typed-404 on unknown job id. Excluded from default mvn
test; activate with -Dgroups=integration.
CI + docs
=========
* .github/workflows/publish-sdks.yaml: versions:set now uses
-DprocessAllModules=true so child modules' versions track the
parent on tag push.
* sdks/java/README.md: starter quickstart, examples table, retry +
AutoCloseable docs, integration-test invocation.
mvn verify is green: 48 unit + 5 starter + 5 integration when
FLYDOCS_BASE_URL is set, 5 cleanly skipped otherwise.
ancongui
added a commit
that referenced
this pull request
May 19, 2026
* chore: clean up ruff findings introduced by #23 / #24 / #25 The Lint check failed on all three merged PRs because the new files tripped ``F401`` (unused ``typing.Any``), ``SIM105`` (replace ``try``/``except``/``pass`` with ``contextlib.suppress``), ``UP041`` (replace ``asyncio.TimeoutError`` with builtin ``TimeoutError``), ``I001`` (import ordering), and ``F841`` (unused local). The other CI jobs (Unit tests, SDK Python, SDK Java, Typecheck, Docling) were all green on each PR; the merges weren't gated on Lint. This is the follow-up sweep so ``ruff check`` is clean on ``main``. 11 errors fixed (8 auto-fixed by ``ruff --fix``, 3 manual). * chore: apply ``ruff format`` to the same files The Lint job runs both ``ruff check`` and ``ruff format --check``. The previous commit cleared the ``check`` half; this one runs ``ruff format`` over the 8 files in the same change set so the formatter half passes too. No behaviour change. --------- Co-authored-by: ancongui <andres.contreras@soon.es>
6 tasks
ancongui
added a commit
that referenced
this pull request
May 31, 2026
…ve integration (#25) Restructures the Java SDK into a 3-module Maven build and ships the "best" Boot 3.5.9 reactive surface in one pass: flydocs-sdk (core) ================== * AutoCloseable on both FlydocsClient and FlydocsClientAsync -- the Netty ConnectionProvider is owned and disposed on close(). * Opt-in retry filter via Builder.maxAttempts(N) + retryMinBackoff. Retries transient 5xx + timeouts with exponential backoff; never retries 4xx (intentional state like 409 job_not_cancellable). * Builder knobs: maxConnections, pendingAcquireTimeout, maxInMemorySize -- bounded pool + caller-tunable buffer limits. * waitForCompletion: replaced the recursive flatMap with Mono.defer + repeatWhenEmpty + outer timeout -- one timeout subscriber, no nested chain. * Cleaned up redundant codec config (was setting maxInMemorySize twice). flydocs-spring-boot-starter (NEW) ================================= * FlydocsAutoConfiguration with @autoConfiguration + @ConditionalOnClass + @ConditionalOnProperty(prefix="flydocs", name="base-url"). * FlydocsProperties: timeout, max-attempts, retry-min-backoff, max-connections, pending-acquire-timeout, max-in-memory-size, tenant-id, webhook.hmac-secret. * @ConditionalOnMissingBean on every produced bean so users can override with a custom @bean. * Bean destroyMethod="close" so the Netty pool is released cleanly on Spring context shutdown. * WebhookVerifier bean conditional on flydocs.webhook.hmac-secret. * spring-boot-configuration-processor for IDE completion in application.yaml. * META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports so Spring Boot 3.x discovery picks it up without spring.factories. * 5 tests using ApplicationContextRunner cover the conditional wiring, user-bean override, and property binding. flydocs-examples (NEW; not deployed) ==================================== Six runnable example classes in 1:1 parity with the Python SDK: FirstExtractionExample (01_first_extraction.py) TypedSchemaAndRulesExample (02_typed_schema_and_rules.py) AsyncJobWithWaitExample (03_async_job_with_wait.py) WebhookReceiverApplication (04_webhook_receiver_fastapi.py) ErrorHandlingExample (05_error_handling.py) SyncFacadeExample (06_sync_facade.py) + ExampleHelpers fixture mirror of examples_helpers.py. maven.deploy.skip=true so the module compile-checks but never ships. Live integration tests ====================== LiveApiIntegrationTest in flydocs-sdk/src/test/.../integration/, tagged @tag("integration") and gated on FLYDOCS_BASE_URL. Verified end-to-end against a running service: version, health, validate, listJobs, typed-404 on unknown job id. Excluded from default mvn test; activate with -Dgroups=integration. CI + docs ========= * .github/workflows/publish-sdks.yaml: versions:set now uses -DprocessAllModules=true so child modules' versions track the parent on tag push. * sdks/java/README.md: starter quickstart, examples table, retry + AutoCloseable docs, integration-test invocation. mvn verify is green: 48 unit + 5 starter + 5 integration when FLYDOCS_BASE_URL is set, 5 cleanly skipped otherwise. Co-authored-by: ancongui <andres.contreras@soon.es>
ancongui
added a commit
that referenced
this pull request
May 31, 2026
* chore: clean up ruff findings introduced by #23 / #24 / #25 The Lint check failed on all three merged PRs because the new files tripped ``F401`` (unused ``typing.Any``), ``SIM105`` (replace ``try``/``except``/``pass`` with ``contextlib.suppress``), ``UP041`` (replace ``asyncio.TimeoutError`` with builtin ``TimeoutError``), ``I001`` (import ordering), and ``F841`` (unused local). The other CI jobs (Unit tests, SDK Python, SDK Java, Typecheck, Docling) were all green on each PR; the merges weren't gated on Lint. This is the follow-up sweep so ``ruff check`` is clean on ``main``. 11 errors fixed (8 auto-fixed by ``ruff --fix``, 3 manual). * chore: apply ``ruff format`` to the same files The Lint job runs both ``ruff check`` and ``ruff format --check``. The previous commit cleared the ``check`` half; this one runs ``ruff format`` over the 8 files in the same change set so the formatter half passes too. No behaviour change. --------- Co-authored-by: ancongui <andres.contreras@soon.es>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A four-axis pass on the Java SDK requested by the user:
flydocs-examples/.flydocs-spring-boot-starterautoconfig module -- one-line drop-in for any Boot 3.5.x app.AutoCloseable, opt-in retry, cleanerwaitForCompletion, bounded Netty pool.The SDK is now structured as a Maven multi-module under
sdks/java/:What changed in the core (
flydocs-sdk)FlydocsClient+FlydocsClientAsyncimplementAutoCloseableConnectionProvideris owned by the client and released onclose(). The starter wires this viadestroyMethod="close".Builder.maxAttempts(N).retryMinBackoff(d))waitForCompletionrewritten onrepeatWhenEmptymaxConnections,pendingAcquireTimeout,maxInMemorySize.codecs()+.exchangeStrategies()were both settingmaxInMemorySize; consolidated.What
flydocs-spring-boot-starterdoes@AutoConfiguration+@ConditionalOnClass(FlydocsClientAsync.class)+@ConditionalOnProperty("flydocs.base-url")-- only activates when the SDK is on the classpath AND the base URL is configured.@ConditionalOnMissingBeanon every produced bean -- user@Beanoverrides win.destroyMethod="close"-- the Netty pool is released cleanly on context shutdown.WebhookVerifieronly published whenflydocs.webhook.hmac-secretis set.spring-boot-configuration-processorfor IDE completion inapplication.yaml.META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Boot 3.x discovery).Examples (1:1 with Python)
FirstExtractionExample01_first_extraction.pyTypedSchemaAndRulesExample02_typed_schema_and_rules.pyAsyncJobWithWaitExample03_async_job_with_wait.pyWebhookReceiverApplication04_webhook_receiver_fastapi.pyErrorHandlingExample05_error_handling.pySyncFacadeExample06_sync_facade.pyPlus
ExampleHelpersmirroringexamples_helpers.py.maven.deploy.skip=trueso the module is compile-checked but never published.Live integration
flydocs-sdk/src/test/.../integration/LiveApiIntegrationTest--@Tag("integration"),@EnabledIfEnvironmentVariable("FLYDOCS_BASE_URL"). 5 tests coveringversion,health,validate,listJobs, typed-404. Activate with:FLYDOCS_BASE_URL=http://localhost:8400 \ mvn -pl flydocs-sdk test -Dgroups=integrationVerified against a real running service before this PR (5/5 passing).
CI
.github/workflows/publish-sdks.yaml:versions:setnow uses-DprocessAllModules=trueso child versions track the parent on tag push. The reactor publishesflydocs-sdkandflydocs-spring-boot-starter;flydocs-examplesis built (compile-check) but never deployed.Test plan
mvn verifyfromsdks/java: 48 unit + 5 starter = 53 passing, 5 integration cleanly skipped.FLYDOCS_BASE_URL=http://localhost:8400 mvn -pl flydocs-sdk test -Dgroups=integration: 5/5 passing against a live API.mvn -pl flydocs-examples compile exec:java -Dexec.mainClass=...works for each example.