diff --git a/docs/migration-4.x.md b/docs/migration-4.x.md index 336d1f34a..960c0d38e 100644 --- a/docs/migration-4.x.md +++ b/docs/migration-4.x.md @@ -199,6 +199,41 @@ code change to `SymphonyBdkBuilder` usage required. Before switching, be aware o `symphony-bdk-http-jdk` is currently `@API(status = API.Status.EXPERIMENTAL)`. If you need an `@API(STABLE)`-only dependency tree, stay on `symphony-bdk-http-jersey` for now. +### 4.2: Spring modules complete the default-to-JDK migration + +Through 4.0 and 4.1, `symphony-bdk-core-spring-boot-starter` was the one exception to the above: `BdkCoreConfig` +still depended on `symphony-bdk-http-jersey` at `implementation` scope and hardcoded +`new ApiClientBuilderProviderJersey2()`, so Spring Boot consumers kept getting the Jersey transport by default +regardless of the rest of the BDK's direction. BDK 4.2 closes that last gap: the starter now depends on +`symphony-bdk-http-jdk` at `implementation` scope instead, and `BdkCoreConfig` exposes a +`@Bean @ConditionalOnMissingBean ApiClientBuilderProvider` returning `ApiClientBuilderProviderJdk`, wired into the +`ApiClientFactory` bean — mirroring plain `symphony-bdk-core`'s behaviour. + +**For most Spring Boot applications, this is transparent.** If your application only consumes the starter's +auto-configured beans (`agentApiClient`, `podApiClient`, `loginApiClient`, and the services built on top of them) and +does not declare its own `ApiClientBuilderProvider` or `ApiClientFactory` bean, no code change is required — Spring +Boot's dependency management pulls in `symphony-bdk-http-jdk` transitively and the transport switches automatically. + +**Possible breaking changes to check before upgrading:** + +- **The Jersey-vs-JDK behavioral differences described above now reach Spring consumers too.** The read-timeout + (total timeout vs. read-only timeout) and filter-support (`Function`-only + vs. JAX-RS `ClientRequestFilter`/`ClientResponseFilter`) differences apply to every Spring Boot application using + the default starter configuration, not just direct `symphony-bdk-core` users. Check any custom `ApiClientBuilder` + filter or read-timeout-dependent long-running request after upgrading. +- **`BdkCoreConfig` subclasses overriding `apiClientFactory(SymphonyBdkCoreProperties)` lose bean registration.** That + single-argument method is no longer annotated `@Bean` — it is kept only as a source-compatible overload delegating + to the new two-argument, `@Bean`-annotated `apiClientFactory(properties, apiClientBuilderProvider)`. A custom + configuration that subclassed `BdkCoreConfig` and overrode the single-argument method expecting Spring to invoke it + as the factory bean will now see that override silently ignored; override the two-argument method instead, or + declare your own `ApiClientBuilderProvider` bean. +- **`symphony-bdk-http-jersey` no longer rides in transitively through the starter.** It is retained at + `testImplementation` scope inside the starter module itself (for internal `MockApiClient` test fixture + compatibility only), not exposed to consumer applications. If your application relied on Jersey/JAX-RS classes + being present purely because the starter pulled them in, add `symphony-bdk-http-jersey` (or + `symphony-bdk-http-webclient`) explicitly and declare your own `ApiClientBuilderProvider` bean to keep the previous + transport. + ## Support window BDK 3.x will receive critical security fixes for **6 months** following the BDK 4.0.0 release, where Symphony is diff --git a/docs/migration.md b/docs/migration.md index ad442e9f1..86ea77e27 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -116,7 +116,7 @@ Simply update BDK dependency version to `3.0.0` org.finos.symphony.bdk - symphony-bdk-http-jersey + symphony-bdk-http-jdk runtime @@ -138,7 +138,7 @@ This guide provides information about how to migrate from Symphony SDK 1.0 to BD ## Dependencies In Java SDK 1.0, the bot had dependencies on `symphony-api-client-java` in addition to the application framework (SpringBoot for e.g). With BDK 2.0, we can replace both of them with `symphony-bdk-core-spring-boot-starter`. -If your project is not framework based, dependencies such as *jersey* and *freemarker* should be added as well. +If your project is not framework based, dependencies such as *http-jdk* and *freemarker* should be added as well. ### Spring Boot based project #### Java SDK 1.0 @@ -219,7 +219,7 @@ If your project is not framework based, dependencies such as *jersey* and *freem org.finos.symphony.bdk - symphony-bdk-http-jersey + symphony-bdk-http-jdk runtime diff --git a/openspec/changes/archive/2026-10-05-switch-default-http-jdk/.openspec.yaml b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/.openspec.yaml new file mode 100644 index 000000000..ad94badae --- /dev/null +++ b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-02 diff --git a/openspec/changes/archive/2026-10-05-switch-default-http-jdk/design.md b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/design.md new file mode 100644 index 000000000..a1cf2a424 --- /dev/null +++ b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/design.md @@ -0,0 +1,65 @@ +## Context + +See `proposal.md` for background and motivation. `symphony-bdk-http-jdk` provides a complete implementation of `com.symphony.bdk.http.api.ApiClient` using the standard JDK 11+ `java.net.http.HttpClient`. However, `symphony-bdk-core-spring-boot-starter` still depended on `symphony-bdk-http-jersey` at `implementation` scope and hardcoded `new ApiClientBuilderProviderJersey2()` in `BdkCoreConfig`, preventing users from benefiting from the zero-dependency transport out-of-the-box. + +## Goals / Non-Goals + +**Goals:** +- Make `symphony-bdk-http-jdk` the default HTTP client for `symphony-bdk-core-spring-boot-starter`, `symphony-bdk-cli`, and example modules. +- Make the HTTP transport pluggable in Spring Boot by exposing an `ApiClientBuilderProvider` bean. +- Maintain full backward compatibility for Spring Boot configurations and `ApiClientFactory` calls. +- Maintain isolated test compatibility for test fixtures that depend on `MockApiClient`. + +**Non-Goals:** +- Removing or altering the behavior of `symphony-bdk-http-jersey` or `symphony-bdk-http-webclient` (they remain supported alternatives). +- Rewriting `MockApiClient` in `symphony-bdk-core`'s internal test harness. + +## Decisions + +### D1: Expose `ApiClientBuilderProvider` as an injectable Spring bean +In `BdkCoreConfig`: +```java +@Bean +@ConditionalOnMissingBean +public ApiClientBuilderProvider apiClientBuilderProvider() { + return new ApiClientBuilderProviderJdk(); +} + +@Bean +@ConditionalOnMissingBean +public ApiClientFactory apiClientFactory(SymphonyBdkCoreProperties properties, + ApiClientBuilderProvider apiClientBuilderProvider) { + return new ApiClientFactory(properties, apiClientBuilderProvider); +} +``` +**Rationale**: This enables consumers to easily plug in an alternative transport (e.g. `symphony-bdk-http-jersey` or `symphony-bdk-http-webclient`) simply by declaring an `ApiClientBuilderProvider` bean, without needing to replace or re-implement the entire `ApiClientFactory` bean. + +### D2: Retain single-parameter `apiClientFactory` overload for source compatibility +Provide: +```java +public ApiClientFactory apiClientFactory(SymphonyBdkCoreProperties properties) { + return apiClientFactory(properties, apiClientBuilderProvider()); +} +``` +**Rationale**: Existing Java unit tests or custom configurations invoking `config.apiClientFactory(properties)` directly continue to compile and function without modification. + +### D3: Scope `symphony-bdk-http-jersey` strictly to `testImplementation` in starter +In `symphony-bdk-core-spring-boot-starter/build.gradle`: +- `implementation project(':symphony-bdk-http:symphony-bdk-http-jdk')` +- `testImplementation project(':symphony-bdk-http:symphony-bdk-http-jersey')` + +And in `SymphonyBdkMockedConfiguration$ApiClientFactoryMock`: +```java +public ApiClientFactoryMock(BdkConfig config) { + super(config, new ApiClientBuilderProviderJdk()); +} +``` +**Rationale**: `MockApiClient` (inherited from `symphony-bdk-core` test output) relies on Jersey's `ApiClientJersey2` and `RuntimeDelegate` at test time. Retaining Jersey in `testImplementation` allows tests to run without leaking Jersey into consumer runtime classpaths. Explicitly passing `ApiClientBuilderProviderJdk` to `super(...)` prevents `ServiceLookup.lookupSingleService` from encountering multiple SPI implementations during tests. + +### D4: Update CLI distribution and examples to runtimeOnly JDK +CLI distribution (`symphony-bdk-cli`) and examples (`bdk-ai-agent-example`, `bdk-core-examples`, `bdk-group-example`, `bdk-multi-instances-example`) bundle or reference `symphony-bdk-http-jdk` at `runtimeOnly` (or `implementation`) scope, eliminating obsolete Jersey dependencies. + +## Risks / Trade-offs + +- **[Risk] Behavioral difference between JDK HttpClient and Jersey client (e.g. read timeout semantics)** → Documented in `docs/migration-4.x.md`; consumers requiring Jersey can supply an `ApiClientBuilderProvider` bean or dependency override. +- **[Risk] Multiple SPI providers on classpath if consumer adds both jars** → `ServiceLookup` fails fast with an explicit error message prompting the user to remove one of the conflicting dependencies. diff --git a/openspec/changes/archive/2026-10-05-switch-default-http-jdk/proposal.md b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/proposal.md new file mode 100644 index 000000000..19c28ac44 --- /dev/null +++ b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/proposal.md @@ -0,0 +1,25 @@ +## Why + +In Symphony BDK 4.x, `symphony-bdk-http-jdk` was introduced as the zero-third-party-dependency HTTP client built on Java 11+ `java.net.http.HttpClient` and documented as the recommended default transport for BDK 4.x. However, `symphony-bdk-core-spring-boot-starter` still pulled in `symphony-bdk-http-jersey` as a direct `implementation` dependency and hardcoded `new ApiClientBuilderProviderJersey2()` in `BdkCoreConfig`. + +This forced all Spring Boot starter consumers to transitively pull in the heavy Jersey 3 stack, JAX-RS APIs, and Apache HttpClient 5, exposing applications to unnecessary CVE attack surface and preventing easy pluggability. Furthermore, the CLI distribution and example projects still bundled or implemented `symphony-bdk-http-jersey`. Switching `symphony-bdk-spring` and the rest of the workspace to default to `symphony-bdk-http-jdk` fulfills the BDK 4.x architecture vision of a lightweight, zero-third-party default transport. + +## What Changes + +- **Spring Boot Starter default dependency**: In `symphony-bdk-core-spring-boot-starter`, replace the `implementation` dependency on `symphony-bdk-http-jersey` with `symphony-bdk-http-jdk`. +- **Spring Boot Starter transport pluggability**: In `BdkCoreConfig`, expose a `@ConditionalOnMissingBean` bean of type `ApiClientBuilderProvider` returning `ApiClientBuilderProviderJdk`, and inject it into `apiClientFactory`. Retain a backwards-compatible overload `apiClientFactory(properties)`. +- **Spring Boot Starter test isolation**: Retain `testImplementation project(':symphony-bdk-http:symphony-bdk-http-jersey')` in `symphony-bdk-core-spring-boot-starter` for internal `MockApiClient` compatibility, and pass `ApiClientBuilderProviderJdk` explicitly in `ApiClientFactoryMock` to prevent classpath SPI lookup conflicts during testing. +- **CLI distribution runtime**: Switch `symphony-bdk-cli` distribution runtime dependency from `symphony-bdk-http-jersey` to `symphony-bdk-http-jdk`. +- **Example projects**: Switch `bdk-ai-agent-example`, `bdk-core-examples`, `bdk-group-example`, and `bdk-multi-instances-example` to use `symphony-bdk-http-jdk` as their runtime/default HTTP transport, removing unused Jersey dependencies from `bdk-core-examples`. +- **Documentation**: Update `docs/migration.md` to reference `symphony-bdk-http-jdk` as the default runtime HTTP dependency. + +## Capabilities + +### Modified Capabilities +- `jdk-http-transport`: Adds requirements for Spring Boot starter default transport wiring, transport pluggability via Spring bean override, and CLI distribution runtime default. + +## Impact + +- **Dependencies**: Spring Boot applications using `symphony-bdk-core-spring-boot-starter` will now transitively receive `symphony-bdk-http-jdk` instead of `symphony-bdk-http-jersey`. Applications desiring Jersey or WebClient can declare their respective dependency and provide an `ApiClientBuilderProvider` bean or `ApiClientFactory` bean. +- **Transitive CVE surface**: Eliminates Jersey, JAX-RS, and Apache HttpClient from the default starter and CLI dependency trees. +- **Compatibility**: Fully backward compatible for Spring Boot applications using standard BDK starter configurations. diff --git a/openspec/changes/archive/2026-10-05-switch-default-http-jdk/specs/jdk-http-transport/spec.md b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/specs/jdk-http-transport/spec.md new file mode 100644 index 000000000..5583dddf1 --- /dev/null +++ b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/specs/jdk-http-transport/spec.md @@ -0,0 +1,26 @@ +## ADDED Requirements + +### Requirement: Spring Boot Starter Default Transport +The `symphony-bdk-core-spring-boot-starter` module SHALL declare `symphony-bdk-http-jdk` as its default `implementation` HTTP client dependency, and instantiate `ApiClientBuilderProviderJdk` by default. + +#### Scenario: Spring Boot application startup with default starter +- **WHEN** a Spring Boot application starts with `symphony-bdk-core-spring-boot-starter` and no custom HTTP client beans +- **THEN** the application context creates an `ApiClientFactory` backed by `ApiClientBuilderProviderJdk` and connects using Java's built-in `HttpClient` + +#### Scenario: No Jersey runtime required +- **WHEN** a consumer includes only `symphony-bdk-core-spring-boot-starter` without `symphony-bdk-http-jersey` +- **THEN** application compilation and runtime execution succeed without Jersey or Apache HttpClient classes on the classpath + +### Requirement: Spring Boot Starter Transport Pluggability +The `BdkCoreConfig` configuration class SHALL expose an `ApiClientBuilderProvider` bean annotated with `@ConditionalOnMissingBean` to allow overriding the HTTP transport via standard Spring bean definition. + +#### Scenario: Custom ApiClientBuilderProvider bean provided +- **WHEN** a Spring Boot application defines a custom bean implementing `ApiClientBuilderProvider` +- **THEN** the custom provider is injected into `ApiClientFactory` instead of `ApiClientBuilderProviderJdk` + +### Requirement: CLI Distribution Default Transport +The `symphony-bdk-cli` application module SHALL package `symphony-bdk-http-jdk` as its runtime HTTP implementation for the standalone CLI distribution. + +#### Scenario: Running CLI command +- **WHEN** the standalone `bdk` CLI distribution binary executes an API command against Symphony +- **THEN** the command uses `ApiClientJdk` without external third-party HTTP client libraries diff --git a/openspec/changes/archive/2026-10-05-switch-default-http-jdk/tasks.md b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/tasks.md new file mode 100644 index 000000000..193207660 --- /dev/null +++ b/openspec/changes/archive/2026-10-05-switch-default-http-jdk/tasks.md @@ -0,0 +1,25 @@ +## 1. Spring Boot Starter HTTP Transport + +- [x] 1.1 In `symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/build.gradle`, replace `implementation project(':symphony-bdk-http:symphony-bdk-http-jersey')` with `implementation project(':symphony-bdk-http:symphony-bdk-http-jdk')` and retain `testImplementation project(':symphony-bdk-http:symphony-bdk-http-jersey')`. +- [x] 1.2 In `BdkCoreConfig`, expose `@Bean @ConditionalOnMissingBean ApiClientBuilderProvider` returning `ApiClientBuilderProviderJdk`. +- [x] 1.3 In `BdkCoreConfig`, inject `ApiClientBuilderProvider` into `apiClientFactory`, and add single-argument `apiClientFactory(properties)` delegation overload for source compatibility. +- [x] 1.4 In `SymphonyBdkMockedConfiguration$ApiClientFactoryMock`, explicitly pass `new ApiClientBuilderProviderJdk()` to `super(...)` to prevent classpath `ServiceLookup` conflicts. +- [x] 1.5 In `BdkCoreConfigTest`, add unit tests verifying `apiClientBuilderProvider()` produces `ApiClientBuilderProviderJdk` by default and custom provider injection works with `apiClientFactory`. +- [x] 1.6 Verify `symphony-bdk-core-spring-boot-starter` and `symphony-bdk-app-spring-boot-starter` build and tests pass via `./gradlew :symphony-bdk-spring:symphony-bdk-core-spring-boot-starter:check :symphony-bdk-spring:symphony-bdk-app-spring-boot-starter:check`. + +## 2. CLI and Example Modules + +- [x] 2.1 In `symphony-bdk-cli/build.gradle`, switch bundled runtime dependency from `symphony-bdk-http-jersey` to `symphony-bdk-http-jdk`. +- [x] 2.2 In `symphony-bdk-examples/bdk-ai-agent-example/build.gradle`, switch `symphony-bdk-http-jersey` to `symphony-bdk-http-jdk`. +- [x] 2.3 In `symphony-bdk-examples/bdk-core-examples/build.gradle`, remove unused Jersey client/multipart dependencies and switch to `runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk')`. +- [x] 2.4 In `symphony-bdk-examples/bdk-group-example/build.gradle`, switch `symphony-bdk-http-jersey` to `symphony-bdk-http-jdk`. +- [x] 2.5 In `symphony-bdk-examples/bdk-multi-instances-example/build.gradle`, add `runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk')`. +- [x] 2.6 Verify CLI and all examples build and pass tests via `./gradlew :symphony-bdk-cli:check :symphony-bdk-examples:bdk-core-examples:check :symphony-bdk-examples:bdk-spring-boot-example:check :symphony-bdk-examples:bdk-app-spring-boot-example:check :symphony-bdk-examples:bdk-ai-agent-example:check :symphony-bdk-examples:bdk-group-example:check :symphony-bdk-examples:bdk-multi-instances-example:check`. + +## 3. Documentation + +- [x] 3.1 In `docs/migration.md`, update Maven dependency snippets and prose references from `symphony-bdk-http-jersey` to `symphony-bdk-http-jdk`. + +## 4. End-to-End Validation + +- [x] 4.1 Run full project verification via `./gradlew check` and confirm all tasks succeed. diff --git a/openspec/specs/jdk-http-transport/spec.md b/openspec/specs/jdk-http-transport/spec.md index 58dda049f..9481387e4 100644 --- a/openspec/specs/jdk-http-transport/spec.md +++ b/openspec/specs/jdk-http-transport/spec.md @@ -101,3 +101,28 @@ When the expected return type is `File`, `ApiClientJdk` SHALL stream the respons - **WHEN** a request sent through `ApiClientJdk` receives a response - **THEN** a DEBUG-level log entry is written to `com.symphony.bdk.requests.outgoing` containing the response status code, the request URL, and the elapsed time +### Requirement: Spring Boot Starter Default Transport +The `symphony-bdk-core-spring-boot-starter` module SHALL declare `symphony-bdk-http-jdk` as its default `implementation` HTTP client dependency, and instantiate `ApiClientBuilderProviderJdk` by default. + +#### Scenario: Spring Boot application startup with default starter +- **WHEN** a Spring Boot application starts with `symphony-bdk-core-spring-boot-starter` and no custom HTTP client beans +- **THEN** the application context creates an `ApiClientFactory` backed by `ApiClientBuilderProviderJdk` and connects using Java's built-in `HttpClient` + +#### Scenario: No Jersey runtime required +- **WHEN** a consumer includes only `symphony-bdk-core-spring-boot-starter` without `symphony-bdk-http-jersey` +- **THEN** application compilation and runtime execution succeed without Jersey or Apache HttpClient classes on the classpath + +### Requirement: Spring Boot Starter Transport Pluggability +The `BdkCoreConfig` configuration class SHALL expose an `ApiClientBuilderProvider` bean annotated with `@ConditionalOnMissingBean` to allow overriding the HTTP transport via standard Spring bean definition. + +#### Scenario: Custom ApiClientBuilderProvider bean provided +- **WHEN** a Spring Boot application defines a custom bean implementing `ApiClientBuilderProvider` +- **THEN** the custom provider is injected into `ApiClientFactory` instead of `ApiClientBuilderProviderJdk` + +### Requirement: CLI Distribution Default Transport +The `symphony-bdk-cli` application module SHALL package `symphony-bdk-http-jdk` as its runtime HTTP implementation for the standalone CLI distribution. + +#### Scenario: Running CLI command +- **WHEN** the standalone `bdk` CLI distribution binary executes an API command against Symphony +- **THEN** the command uses `ApiClientJdk` without external third-party HTTP client libraries + diff --git a/symphony-bdk-cli/build.gradle b/symphony-bdk-cli/build.gradle index 9f3b000bb..5e639f885 100644 --- a/symphony-bdk-cli/build.gradle +++ b/symphony-bdk-cli/build.gradle @@ -24,7 +24,7 @@ dependencies { implementation project(':symphony-bdk-core') // self-contained distribution: bundle an HTTP implementation and a logging backend - runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jersey') + runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk') runtimeOnly project(':symphony-bdk-template:symphony-bdk-template-freemarker') // command-line parsing diff --git a/symphony-bdk-examples/bdk-ai-agent-example/build.gradle b/symphony-bdk-examples/bdk-ai-agent-example/build.gradle index ef777140f..859d2fbc8 100644 --- a/symphony-bdk-examples/bdk-ai-agent-example/build.gradle +++ b/symphony-bdk-examples/bdk-ai-agent-example/build.gradle @@ -13,7 +13,7 @@ dependencies { implementation project(':symphony-bdk-core') runtimeOnly project(':symphony-bdk-template:symphony-bdk-template-freemarker') - implementation project(':symphony-bdk-http:symphony-bdk-http-jersey') + implementation project(':symphony-bdk-http:symphony-bdk-http-jdk') implementation platform("dev.langchain4j:langchain4j-bom:${langchain4jVersion}") implementation 'dev.langchain4j:langchain4j' diff --git a/symphony-bdk-examples/bdk-core-examples/build.gradle b/symphony-bdk-examples/bdk-core-examples/build.gradle index dd49ae9e0..886a3f4c9 100644 --- a/symphony-bdk-examples/bdk-core-examples/build.gradle +++ b/symphony-bdk-examples/bdk-core-examples/build.gradle @@ -10,10 +10,7 @@ dependencies { runtimeOnly project(':symphony-bdk-template:symphony-bdk-template-freemarker') - // for advanced configuration of the JerseyClient - implementation project(':symphony-bdk-http:symphony-bdk-http-jersey') - implementation 'org.glassfish.jersey.core:jersey-client' - implementation 'org.glassfish.jersey.media:jersey-media-multipart' + runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk') runtimeOnly 'ch.qos.logback:logback-classic' diff --git a/symphony-bdk-examples/bdk-group-example/build.gradle b/symphony-bdk-examples/bdk-group-example/build.gradle index 36bc1739c..1d622631f 100644 --- a/symphony-bdk-examples/bdk-group-example/build.gradle +++ b/symphony-bdk-examples/bdk-group-example/build.gradle @@ -9,7 +9,7 @@ dependencies { implementation project(':symphony-bdk-core') runtimeOnly project(':symphony-bdk-template:symphony-bdk-template-freemarker') - runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jersey') + runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk') // import the extension implementation project(':symphony-bdk-extensions:symphony-group-extension') diff --git a/symphony-bdk-examples/bdk-multi-instances-example/build.gradle b/symphony-bdk-examples/bdk-multi-instances-example/build.gradle index 5111cbf51..a036db06f 100644 --- a/symphony-bdk-examples/bdk-multi-instances-example/build.gradle +++ b/symphony-bdk-examples/bdk-multi-instances-example/build.gradle @@ -9,6 +9,7 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' implementation project(':symphony-bdk-core') + runtimeOnly project(':symphony-bdk-http:symphony-bdk-http-jdk') implementation 'org.slf4j:slf4j-api' implementation 'com.hazelcast:hazelcast:5.3.6' diff --git a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/build.gradle b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/build.gradle index 5a7350e36..87ce1e899 100644 --- a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/build.gradle +++ b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/build.gradle @@ -28,7 +28,8 @@ jacocoTestCoverageVerification { dependencies { api project(':symphony-bdk-core') api project(':symphony-bdk-http:symphony-bdk-http-api') - implementation project(':symphony-bdk-http:symphony-bdk-http-jersey') + implementation project(':symphony-bdk-http:symphony-bdk-http-jdk') + testImplementation project(':symphony-bdk-http:symphony-bdk-http-jersey') api project(':symphony-bdk-template:symphony-bdk-template-api') implementation project(':symphony-bdk-template:symphony-bdk-template-freemarker') diff --git a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/main/java/com/symphony/bdk/spring/config/BdkCoreConfig.java b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/main/java/com/symphony/bdk/spring/config/BdkCoreConfig.java index de3fc0025..30ed49ad2 100644 --- a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/main/java/com/symphony/bdk/spring/config/BdkCoreConfig.java +++ b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/main/java/com/symphony/bdk/spring/config/BdkCoreConfig.java @@ -14,7 +14,8 @@ import com.symphony.bdk.core.client.ApiClientFactory; import com.symphony.bdk.core.config.model.BdkConfig; import com.symphony.bdk.http.api.ApiClient; -import com.symphony.bdk.http.jersey2.ApiClientBuilderProviderJersey2; +import com.symphony.bdk.http.api.ApiClientBuilderProvider; +import com.symphony.bdk.http.jdk.ApiClientBuilderProviderJdk; import com.symphony.bdk.spring.SymphonyBdkCoreProperties; import com.symphony.bdk.template.api.TemplateEngine; import com.symphony.bdk.template.freemarker.FreeMarkerEngine; @@ -35,9 +36,19 @@ public class BdkCoreConfig { @Bean @ConditionalOnMissingBean + public ApiClientBuilderProvider apiClientBuilderProvider() { + return new ApiClientBuilderProviderJdk(); + } + + @Bean + @ConditionalOnMissingBean + public ApiClientFactory apiClientFactory(SymphonyBdkCoreProperties properties, + ApiClientBuilderProvider apiClientBuilderProvider) { + return new ApiClientFactory(properties, apiClientBuilderProvider); + } + public ApiClientFactory apiClientFactory(SymphonyBdkCoreProperties properties) { - return new ApiClientFactory(properties, - new ApiClientBuilderProviderJersey2()); // TODO create RestTemplate/or WebClient implementation + return apiClientFactory(properties, apiClientBuilderProvider()); } @Bean(name = "agentApiClient") diff --git a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/SymphonyBdkMockedConfiguration.java b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/SymphonyBdkMockedConfiguration.java index c23f2178e..731579cb1 100644 --- a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/SymphonyBdkMockedConfiguration.java +++ b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/SymphonyBdkMockedConfiguration.java @@ -5,6 +5,7 @@ import com.symphony.bdk.core.test.MockApiClient; import com.symphony.bdk.gen.api.model.UserV2; import com.symphony.bdk.http.api.ApiClient; +import com.symphony.bdk.http.jdk.ApiClientBuilderProviderJdk; import tools.jackson.databind.ObjectMapper; import lombok.SneakyThrows; @@ -65,7 +66,7 @@ public static class ApiClientFactoryMock extends ApiClientFactory { private MockApiClient loginApiClient; public ApiClientFactoryMock(BdkConfig config) { - super(config); + super(config, new ApiClientBuilderProviderJdk()); } @Override diff --git a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/config/BdkCoreConfigTest.java b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/config/BdkCoreConfigTest.java index aa77969ee..f9c7aec99 100644 --- a/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/config/BdkCoreConfigTest.java +++ b/symphony-bdk-spring/symphony-bdk-core-spring-boot-starter/src/test/java/com/symphony/bdk/spring/config/BdkCoreConfigTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -13,6 +14,8 @@ import com.symphony.bdk.core.config.model.BdkCommonJwtConfig; import com.symphony.bdk.core.config.model.BdkConfig; import com.symphony.bdk.http.api.ApiClient; +import com.symphony.bdk.http.api.ApiClientBuilderProvider; +import com.symphony.bdk.http.jdk.ApiClientBuilderProviderJdk; import com.symphony.bdk.spring.SymphonyBdkCoreProperties; import org.junit.jupiter.api.Test; @@ -45,6 +48,22 @@ void shouldCreateApiClientFactory() { assertNotNull(config.apiClientFactory(props)); } + @Test + void shouldCreateApiClientBuilderProvider() { + final BdkCoreConfig config = new BdkCoreConfig(); + final ApiClientBuilderProvider provider = config.apiClientBuilderProvider(); + assertNotNull(provider); + assertTrue(provider instanceof ApiClientBuilderProviderJdk); + } + + @Test + void shouldCreateApiClientFactoryWithCustomProvider() { + final BdkCoreConfig config = new BdkCoreConfig(); + final SymphonyBdkCoreProperties props = new SymphonyBdkCoreProperties(); + final ApiClientBuilderProvider provider = mock(ApiClientBuilderProvider.class); + assertNotNull(config.apiClientFactory(props, provider)); + } + @Test void shouldCreatePodClient() { final BdkCoreConfig config = new BdkCoreConfig();