|
| 1 | +[](https://search.maven.org/artifact/com.expediagroup/expediagroup-sdk-core) |
| 2 | + |
| 3 | +# Expedia Group JVM SDK - Core Module |
| 4 | +The `expediagroup-sdk-core` module serves as a reusable component that abstracts common functionalities, such as HTTP request execution, authentication, logging, and execution pipeline processing. It empowers product SDKs to focus on business-specific logic while ensuring consistency, flexibility, and maintainability. |
| 5 | + |
| 6 | +## Usage |
| 7 | +In most cases, you don’t need to add `expediagroup-sdk-core` directly, just include `expediagroup-sdk-rest` or `expediagroup-sdk-graphql` in your project, and the core module will be pulled in transitively. |
| 8 | + |
| 9 | +<details> |
| 10 | + <summary><strong>Maven</strong></summary> |
| 11 | + |
| 12 | + Add the `expediagroup-sdk-core` as a dependency in your `pom.xml`: |
| 13 | + |
| 14 | + ```xml |
| 15 | + <dependency> |
| 16 | + <groupId>com.expediagroup</groupId> |
| 17 | + <artifactId>expediagroup-sdk-core</artifactId> |
| 18 | + <version>{latest-version}</version> |
| 19 | + </dependency> |
| 20 | + ``` |
| 21 | +</details> |
| 22 | + |
| 23 | + |
| 24 | +<details> |
| 25 | + <summary><strong>Gradle</strong></summary> |
| 26 | + |
| 27 | + Add the `expediagroup-sdk-core` as a dependency in your `build.gradle`: |
| 28 | + |
| 29 | + ```gradle |
| 30 | + implementation 'com.expediagroup:expediagroup-sdk-core:{latest-version}' |
| 31 | + ``` |
| 32 | +</details> |
| 33 | + |
| 34 | +## Architecture & Components |
| 35 | +The SDK Core module serves as the foundational "shell" that abstracts the execution of requests and responses via an **injected** HTTP client. It acts as a toolkit, empowering product SDKs to deliver a polished and user-friendly experience by providing ready-to-use components such as request execution, logging, authentication, and exception handling. The SDK core streamlines the development of cohesive SDKs. |
| 36 | + |
| 37 | +### Transport Package |
| 38 | +The `Transport` interface defines the abstraction layer for making HTTP requests within the SDK. This interface allows SDK users to integrate their preferred HTTP client or transport mechanism while adhering to a standardized contract. The SDK relies on this interface to execute requests and process responses, offering flexibility and compatibility across diverse environments and libraries. To achieve complete abstraction, the SDK core module introduces standardized HTTP models customized for SDK usage (in the http package), such as `Request` and `Response`, which all `Transport` implementations are required to use. These models ensure consistency in how the SDK interacts with external systems, regardless of the underlying HTTP client or transport mechanism. |
| 39 | + |
| 40 | +> [!TIP] |
| 41 | +> Refer to SDK Transport Usage Guide for more information and examples |
| 42 | +
|
| 43 | +### HTTP Package |
| 44 | +As mentioned earlier, the core module doesn’t depend on any specific HTTP client. To make this possible, the SDK defines its own generic HTTP request and response models. At runtime, those SDK models are translated into the native types required by your chosen HTTP client (for example, converting to OkHttp’s `Request` and `Response` objects). |
| 45 | + |
| 46 | +[http package](https://github.com/ExpediaGroup/expediagroup-java-sdk/tree/main/expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/http) |
| 47 | + |
| 48 | +### Pipeline Package |
| 49 | +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. |
| 50 | + |
| 51 | +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. |
| 52 | + |
| 53 | +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. |
| 54 | + |
| 55 | +[pipeline package](https://github.com/ExpediaGroup/expediagroup-java-sdk/tree/main/expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/pipeline) |
| 56 | + |
| 57 | +### Authentication Package |
| 58 | +The core module includes a suite of prebuilt components for handling common authentication schemes - such as Basic Auth & OAuth - so you don’t have to reinvent the wheel. True to the core’s “pluggable pipeline” philosophy, it provides the building blocks for each authentication workflow but leaves it up to the product SDK to decide when to invoke them. |
| 59 | + |
| 60 | +In practice, you simply add one of the supplied pipeline steps (for example, `BasicAuthStep` or `OAuthStep`) to your request execution pipeline. If your product SDK requires a custom authentication mechanism that isn’t yet provided, you can implement the `RequestPipelineStep` interface yourself, insert your new step into the pipeline, and encapsulate all of your custom auth logic there. This approach keeps authentication concerns isolated, consistent, and easy to extend. |
| 61 | + |
| 62 | +[auth package](https://github.com/ExpediaGroup/expediagroup-java-sdk/tree/main/expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/auth) |
| 63 | + |
| 64 | +### Logging Package |
| 65 | +All SDK modules rely on the `SLF4J` API for logging without shipping a concrete implementation, so you remain free to choose any `SLF4J` binding (such as Logback or Log4j2) at runtime. To turn on request and response logging, simply register the built-in `RequestLoggingStep` and `ResponseLoggingStep` in your execution pipeline; as long as you include a valid `SLF4J` binding on your classpath, those steps will automatically emit detailed logs for each outbound HTTP request and inbound HTTP response through your chosen logging framework. |
| 66 | + |
| 67 | +_A product SDK shouldn't provide the SLF4J implementation itself. This should be up to the end-user of the product SDK._ |
| 68 | + |
| 69 | +Beyond basic request and response logging, the core module also lets you automatically redact any sensitive information - whether it lives in HTTP headers or in the body of a request or response - so that secrets never end up in your logs. |
| 70 | + |
| 71 | +[logging package](https://github.com/ExpediaGroup/expediagroup-java-sdk/tree/main/expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/logging) |
| 72 | + |
| 73 | +### Exception Package |
| 74 | +The SDK has a set of exception models each for a defined purpose, categorized based on the exception nature: |
| 75 | +- Client exception: Any exception that might be thrown or caused by the SDK itself (e.g. Configuration exception) |
| 76 | +- Service exception: Any exception that's caused by the remote server (e.g Authentication Exception). |
| 77 | +- All exceptions extend `ExpediaGroupException`. |
| 78 | +- All service exceptions extend `ExpediaGroupServiceException`. |
| 79 | +- All client exceptions extend `ExpediaGroupClientException`. |
| 80 | + |
| 81 | +[exception packagae](https://github.com/ExpediaGroup/expediagroup-java-sdk/tree/main/expediagroup-sdk-core/src/main/kotlin/com/expediagroup/sdk/core/exception) |
| 82 | + |
| 83 | + |
| 84 | +## Metadata Loader |
| 85 | +The core module includes a utility for loading runtime metadata such as SDK name, JVM version, SDK version, locale, etc... from `sdk.properties` file. Each product SDK must bundle this file in its resources, and it’s typically generated automatically during the build process. |
| 86 | + |
| 87 | +## Full Integration View - Diagram |
| 88 | +The diagram below illustrates the architecture and interaction between a product SDK and the SDK Core, highlighting the flow of operations and the role of various components in synchronous and asynchronous request execution. |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +#### Operations & Models |
| 93 | +- Located at the far left, these represent the business-specific **operations** and models defined by the product SDK. These models will be typically **generated** by OpenAPI generator for REST SDKs, and from Apollo Kotlin for GraphQL SDKs. |
| 94 | +- These are entirely decoupled from the core module and are responsible for defining the domain-specific request and response structures. |
| 95 | +- The operations are converted into SDK requests, which are later executed via the core module. |
| 96 | + |
| 97 | +#### Sync Client |
| 98 | +- Represents the high-level client responsible for handling synchronous requests. |
| 99 | +- Converts an operation into a valid SDK request and sends it for execution. |
| 100 | +- Should encapsulate one implementation of `AbstractRequestExecutor` where this client can access the `execute` method along with the execution pipeline. |
| 101 | +- After receiving the response, the sync client converts the SDK response back into the corresponding operation response. |
| 102 | + |
| 103 | +#### Async Client |
| 104 | +- Represents the high-level client handling asynchronous requests. |
| 105 | +- Converts an operation into a valid SDK request and sends it for execution. |
| 106 | +- Should encapsulate one implementation of `AbstractAsyncRequestExecutor` where this client can access the `execute` method along with the execution pipeline. |
| 107 | +- Once the response is received (via a `CompletableFuture`), it is asynchronously converted into the corresponding operation response. |
| 108 | + |
| 109 | +#### Core Module: |
| 110 | +- SDK HTTP Models: Standardized Request and Response objects for consistent communication. |
| 111 | +- Authentication Module: Handles various authentication mechanisms. |
| 112 | +- Logging Module: Enables request/response logging for observability. |
| 113 | +- Metadata Loader: Loads extra runtime information about the SDK such as artifact name, version, Java version, and host OS. |
| 114 | + |
| 115 | +#### Execution Pipelines |
| 116 | +- Request Pipeline: Depicted with blue blocks, this pipeline processes the SDK request through a series of defined steps (e.g., adding headers, logging) before sending it to the transport layer. |
| 117 | +- Response Pipeline: Depicted with green blocks, this pipeline processes the SDK response through defined steps (e.g., logging) after it is received from the transport layer. |
| 118 | + |
| 119 | +#### Transport Layer |
| 120 | +- Sync Transport: Processes synchronous requests and returns a blocking response. |
| 121 | +- Async Transport: Processes asynchronous requests and returns a `CompletableFuture<Response>`. |
| 122 | +- By default, both `Transport` and `AsyncTransport` use the same HTTP client instance. |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | + |
0 commit comments