Skip to content
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

Merged
merged 16 commits into from
Jan 15, 2025

Conversation

Mohammad-Dwairi
Copy link
Contributor

@Mohammad-Dwairi Mohammad-Dwairi commented Jan 12, 2025

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 and AsyncTransport interface. The asynchronous execution model leverages Java’s CompletableFuture to manage asynchronous workflows.

Dynamic Transport Loading

The refactored core module introduces dynamic Transport loading, a feature that utilizes Java's ServiceLoader 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 corresponding Transport or AsyncTransport 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 the AbstractAsyncRequestExecutor for asynchronous calls. These abstract classes enforce a consistent integration pattern by requiring implementers (i.e., product SDKs) to define the necessary ExecutionPipeline. 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 an ExecutionPipeline. 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.

class RequestExecutor(configuration: ClientConfiguration) : AbstractRequestExecutor(configuration.transport) {

    override val executionPipeline = ExecutionPipeline(
        requestPipeline = listOf(
            RequestHeadersStep(),
            RequestLoggingStep(logger)
        ),
        responsePipeline = listOf(
            ResponseLoggingStep(logger)
        )
    )

    companion object {
        private val logger = LoggerDecorator(LoggerFactory.getLogger(this::class.java.enclosingClass))
    }
}

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.

Untitled-4

Testing

Changes in this PR are covered with unit & integration tests.

Lines Coverage Threshold: 100%
Branch Coverage Threshold: 100%

Screenshot 2025-01-14 at 9 03 09 PM

Results

  1. The core module is established and tested.
  2. The new core supports the features agreed on earlier.
  3. The overall setup is more ready for next steps such as graphql extension packages and HTTP clients integration packages.

@Mohammad-Dwairi Mohammad-Dwairi requested a review from a team as a code owner January 12, 2025 13:24
Copy link
Contributor

@jordan-n-schmidt jordan-n-schmidt left a 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.

Copy link
Contributor

@jordan-n-schmidt jordan-n-schmidt left a 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.

Copy link
Contributor

@OmarAlJarrah OmarAlJarrah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣀⡀⠀⠀⠀⡀⢀⣠⣀⡄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣵⡶⢶⣶⣦⣄⣠⠀⠀⡀⠀⠀⠀⠀⠀⢀⣠⣾⣿⢿⡿⣿⣦⣤⣶⡿⠟⠛⠛⢿⣆⠄⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣀⣿⠋⠀⠀⠀⠈⠙⠻⠿⣿⠿⠿⠿⠿⠿⠿⣿⣿⡿⣯⢿⣽⣻⢿⣿⠁⠀⠀⠀⠀⠈⣿⣀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢺⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣽⢻⣿⣿⣿⣿⣿⣿⣶⣦⢠⣤⣤⣿⣯⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣸⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣷⣻⢿⣿⣿⣿⡿⣯⣟⡿⣿⣿⣿⢿⡿⣿⣷⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠙⣿⡾⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣾⣯⣟⣿⣿⣿⣽⣷⣻⣽⣿⣿⣿⣿⣻⣽⣿⠁⠀⠀⠀
⠀⠀⠀⠀⠀⣰⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠉⠉⠙⠿⠾⠿⣾⣿⣿⣿⡿⣽⣾⢏⠁⠀⠀⠀
⠀⠀⠀⠀⢤⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣾⣽⡿⣿⣀⠀⠀⠀⠀
⠀⠀⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠀⢻⡇⠀⠀⠀⠀
⣀⣀⣄⣀⣿⣇⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡴⣾⣿⡶⢶⡶⢆
⠚⠉⠉⠙⢻⡏⠉⠉⠀⠀⠀⢠⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣷⠀⠀⠀⠀⠀⠀⢸⡇⠂⠀⠀⠀
⠀⠀⠀⢠⣺⣿⣤⣤⠀⠀⠀⠈⠻⠟⠀⠀⠀⠀⠀⠀⣀⣤⣤⣄⠀⠀⠀⠀⠀⠘⠻⠋⠀⠀⠀⠀⠐⢳⣿⠷⡾⠦⠔⠀
⠀⠀⠘⠋⠙⠹⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣄⣠⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣼⣏⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣸⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢈⣿⣿⣿⣎⡀⠀⠀⠀
⠀⠀⠀⢠⣴⠿⠋⠉⠙⢿⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⢿⠏⠀⠀⠈⠙⠃⠀⠀
⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠈⠹⣻⣷⣶⣤⣤⣤⣀⣀⣀⣀⣀⣀⣀⣀⣀⣤⣤⣤⣶⣾⠟⡫⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡀⢀⣴⡾⠛⣹⣿⣿⣿⣿⣿⠉⠉⠉⠉⠉⠉⢩⣿⣿⣿⣿⣯⠙⠻⣾⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢀⣨⡾⠟⠟⠻⣷⣴⣿⣿⣿⣟⣿⣿⣧⣀⠀⠀⢀⣠⣿⣿⣿⣟⣿⣿⣧⣴⡿⠛⠻⢷⣆⠄⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢠⢿⡅⠀⠀⠀⢸⣿⣿⣿⣟⣾⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣟⣿⣿⡇⠀⠀⠀⢠⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠈⣿⡇⠀⠀⠀⣾⣿⣿⢿⣾⣿⣽⡿⣯⣿⣟⣿⣿⣻⣿⣾⣟⣷⣿⣟⣿⣷⠀⠀⠀⢸⣿⡀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠘⢿⣦⣀⣸⣿⣿⡿⣿⣻⣾⣟⣿⣿⣽⣿⣻⣾⡿⣷⣿⣻⣿⣾⢿⣻⣿⣧⣠⣴⡿⠃⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠘⠉⢿⣿⣿⢿⣟⣿⣽⣿⣻⣾⢿⣾⣿⣷⣿⢿⣽⣿⣳⣿⡿⣿⣿⣿⠍⠁⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡟⠿⠿⠿⢿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠿⠿⠿⢿⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠐⣿⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⢷⣦⣤⣤⣀⣤⣤⣤⣼⣿⣦⣤⣤⣠⣤⣤⣴⡶⠟⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠉⠉⠉⠉⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

@Mohammad-Dwairi Mohammad-Dwairi merged commit edcee63 into main Jan 15, 2025
2 checks passed
@Mohammad-Dwairi Mohammad-Dwairi deleted the mdwairi/establish-core-module branch January 15, 2025 17:29
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.

4 participants