-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: extract the core package to a separate Gradle module #151
Conversation
core/src/main/kotlin/com/expediagroup/sdk/core/http/RequestBody.kt
Outdated
Show resolved
Hide resolved
core/src/main/kotlin/com/expediagroup/sdk/core/pipeline/step/RequestHeadersStep.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks great. A couple small comments that aren't blocking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left one comment, but won't block the PR.
expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/pipeline/ExecutionPipeline.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣀⡀⠀⠀⠀⡀⢀⣠⣀⡄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣵⡶⢶⣶⣦⣄⣠⠀⠀⡀⠀⠀⠀⠀⠀⢀⣠⣾⣿⢿⡿⣿⣦⣤⣶⡿⠟⠛⠛⢿⣆⠄⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣀⣿⠋⠀⠀⠀⠈⠙⠻⠿⣿⠿⠿⠿⠿⠿⠿⣿⣿⡿⣯⢿⣽⣻⢿⣿⠁⠀⠀⠀⠀⠈⣿⣀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢺⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣽⢻⣿⣿⣿⣿⣿⣿⣶⣦⢠⣤⣤⣿⣯⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣸⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣷⣻⢿⣿⣿⣿⡿⣯⣟⡿⣿⣿⣿⢿⡿⣿⣷⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠙⣿⡾⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣾⣯⣟⣿⣿⣿⣽⣷⣻⣽⣿⣿⣿⣿⣻⣽⣿⠁⠀⠀⠀
⠀⠀⠀⠀⠀⣰⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠉⠉⠙⠿⠾⠿⣾⣿⣿⣿⡿⣽⣾⢏⠁⠀⠀⠀
⠀⠀⠀⠀⢤⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣾⣽⡿⣿⣀⠀⠀⠀⠀
⠀⠀⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠀⢻⡇⠀⠀⠀⠀
⣀⣀⣄⣀⣿⣇⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡴⣾⣿⡶⢶⡶⢆
⠚⠉⠉⠙⢻⡏⠉⠉⠀⠀⠀⢠⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣷⠀⠀⠀⠀⠀⠀⢸⡇⠂⠀⠀⠀
⠀⠀⠀⢠⣺⣿⣤⣤⠀⠀⠀⠈⠻⠟⠀⠀⠀⠀⠀⠀⣀⣤⣤⣄⠀⠀⠀⠀⠀⠘⠻⠋⠀⠀⠀⠀⠐⢳⣿⠷⡾⠦⠔⠀
⠀⠀⠘⠋⠙⠹⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣄⣠⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣼⣏⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣸⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢈⣿⣿⣿⣎⡀⠀⠀⠀
⠀⠀⠀⢠⣴⠿⠋⠉⠙⢿⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⢿⠏⠀⠀⠈⠙⠃⠀⠀
⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠈⠹⣻⣷⣶⣤⣤⣤⣀⣀⣀⣀⣀⣀⣀⣀⣀⣤⣤⣤⣶⣾⠟⡫⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡀⢀⣴⡾⠛⣹⣿⣿⣿⣿⣿⠉⠉⠉⠉⠉⠉⢩⣿⣿⣿⣿⣯⠙⠻⣾⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢀⣨⡾⠟⠟⠻⣷⣴⣿⣿⣿⣟⣿⣿⣧⣀⠀⠀⢀⣠⣿⣿⣿⣟⣿⣿⣧⣴⡿⠛⠻⢷⣆⠄⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢠⢿⡅⠀⠀⠀⢸⣿⣿⣿⣟⣾⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣟⣿⣿⡇⠀⠀⠀⢠⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠈⣿⡇⠀⠀⠀⣾⣿⣿⢿⣾⣿⣽⡿⣯⣿⣟⣿⣿⣻⣿⣾⣟⣷⣿⣟⣿⣷⠀⠀⠀⢸⣿⡀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠘⢿⣦⣀⣸⣿⣿⡿⣿⣻⣾⣟⣿⣿⣽⣿⣻⣾⡿⣷⣿⣻⣿⣾⢿⣻⣿⣧⣠⣴⡿⠃⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠘⠉⢿⣿⣿⢿⣟⣿⣽⣿⣻⣾⢿⣾⣿⣷⣿⢿⣽⣿⣳⣿⡿⣿⣿⣿⠍⠁⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡟⠿⠿⠿⢿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠿⠿⠿⢿⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠐⣿⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢷⣦⣤⣤⣀⣤⣤⣤⣼⣿⣦⣤⣤⣠⣤⣤⣴⡶⠟⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠉⠉⠉⠉⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Situation
We've been developing the refactored core package alongside the
lodging-connectivity-sdk
codebase. However, the long-term plan is to migrate the new core package to its dedicated repository, expediagroup-java-sdk, once it has been fully tested and is ready to integrate with other SDKs.To facilitate this migration and ensure better isolation, this PR establishes a new
core
Gradle module. This separation simplifies the migration process while enabling focused development on the refactored core.Additionally, this PR introduces multiple enhancements to the existing core, such as asynchronous requests execution, execution pipelines, and other general improvements. More details about these changes in the Action section.
Caution
This PR introduces changes that impact multiple areas of the SDK code. To minimize disruption and simplify the migration, the existing core package remains unchanged, and the lodging-connectivity-sdk continues to rely on it. The newly introduced core module temporarily duplicates code from the old package, along with the enhancements. Once the code splitting process is complete, we will clean up the lodging-connectivity-sdk and remove the old core package.
Action
Initializing New Core Gradle Module
The primary objective of this PR is to establish a new core module that consolidates all components related to the SDK Core. As outlined earlier, this new module has been initialized and is ready for use. However, to avoid modifying multiple unrelated parts in this PR, the new module currently contains a copy of the existing core package, which resides locally within the lodging-connectivity-sdk codebase. Once all modules are prepared and fully integrated, we will proceed with cleaning up the old package
Asynchronous Requests Execution Support
One of the new additions to the core module is the asynchronous requests execution support, facilitated through the new
AbstractAsyncRequestExecutor
andAsyncTransport
interface. The asynchronous execution model leverages Java’sCompletableFuture
to manage asynchronous workflows.Dynamic Transport Loading
The refactored
core
module introduces dynamicTransport
loading, a feature that utilizes Java'sServiceLoader
utility to automatically detect and load HTTP transport implementations available on the classpath. This capability gives users the flexibility to choose their preferred HTTP client for request execution with minimal configuration.By simply adding a supported HTTP client integration package as a dependency (e.g.,
expediagroup-sdk-okhttp
), the core module can dynamically load the correspondingTranspor
t orAsyncTransport
implementation. This eliminates the need for manual setup.In the near future, we plan to provide prebuilt integration packages for selected HTTP clients such as OkHttp and Apache HTTP. These packages will offer ready-to-use implementations of the Transport interfaces.
Execution Pipeline
While supporting injectable HTTP clients provides significant flexibility, it is essential to ensure that all requests made by the SDK adhere to governance and observability standards. This includes logging, authentication, client identification, and other critical processes, regardless of the underlying HTTP client being used. To achieve this, the core module introduces an
ExecutionPipeline
, which every product SDK must implement to integrate with the core.Each product SDK defines its own execution pipeline by composing "request pipeline steps" and "response pipeline steps." The core ensures that these steps are executed in the correct sequence: request steps are applied before the request is executed, and response steps are applied after the response is received.
The primary entry point for integrating a product SDK with the core is through the
AbstractRequestExecutor
for synchronous calls and theAbstractAsyncRequestExecutor
for asynchronous calls. These abstract classes enforce a consistent integration pattern by requiring implementers (i.e., product SDKs) to define the necessaryExecutionPipeline
. This guarantees that governance and observability processes are applied consistently across all product SDKs, irrespective of the HTTP client used.The example below illustrates how a product SDK can implement the
AbstractRequestExecutor
and define anExecutionPipeline
. In this example, the request pipeline consists of two steps: the first step sets specific request headers, and the second logs the request details. The response pipeline includes a single step for logging the response.The
RequestExecutor
implementation above resides within the product SDK and can include any additional logic or configurations specific to the product SDK's requirements. The only mandatory requirement is to override and define the ExecutionPipeline, ensuring that the necessary request and response processing steps are executed as part of the core integration.Testing
Changes in this PR are covered with unit & integration tests.
Lines Coverage Threshold: 100%
Branch Coverage Threshold: 100%
Results