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

Develop #101

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d3a5d5c
Refactor to use different Http clients
sashirestela Jan 10, 2025
5c2519b
Add develop branch to build
sashirestela Jan 10, 2025
72b1b9c
Adding constants to avoid duplicated literals
sashirestela Jan 10, 2025
7c079a0
Adding OkHttp as an alternative http client
sashirestela Jan 14, 2025
a083c6a
Refactoring examples to use OkHttp
sashirestela Jan 14, 2025
24a2b73
Refactoring tests to avoid order dependency
sashirestela Jan 15, 2025
20568f6
Refactoring async handling in OkHttp
sashirestela Jan 15, 2025
a5fafbc
Refactoring unit tests to handling many Http clients
sashirestela Jan 15, 2025
dd433b8
Update Readme for OkHttp
sashirestela Jan 16, 2025
223233a
Handling stream closing for OkHttp
sashirestela Jan 16, 2025
9854f23
Handling stream closing for OkHttp
sashirestela Jan 16, 2025
9064e44
Adding test for shutdown
sashirestela Jan 16, 2025
92c86f8
Adding Response Interceptor
sashirestela Jan 17, 2025
8076b18
Example of Response Interceptor
sashirestela Jan 17, 2025
ec7f9c1
Adding unit testing for response interceptor
sashirestela Jan 18, 2025
c47a83a
Fixing code style in examples
sashirestela Jan 18, 2025
b41d8d5
Adding websocket support
sashirestela Jan 22, 2025
26a265e
Adding websocket support
sashirestela Jan 22, 2025
35820a6
Update Readme
sashirestela Jan 22, 2025
b36aef6
Update Readme
sashirestela Jan 22, 2025
cac9e18
Refactor unit test
sashirestela Jan 22, 2025
4affc45
Update Readme
sashirestela Jan 22, 2025
69e37b5
Deploy release 2.0.0
sashirestela Jan 22, 2025
af0305b
Improve dependency between JsonUtil and Configurator
sashirestela Jan 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build_java_maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Java CI with Maven

on:
push:
branches: ["main"]
branches: ["main", "develop"]
pull_request:
branches: ["main"]
branches: ["main", "develop"]

jobs:
build:
Expand Down
114 changes: 86 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 💎 CleverClient

Library that makes it easy to use the Java HttpClient to perform http operations through interfaces.
A Java library for making http client and websocket requests easily.

[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=sashirestela_cleverclient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=sashirestela_cleverclient)
[![codecov](https://codecov.io/gh/sashirestela/cleverclient/graph/badge.svg?token=PEYAFW3EWD)](https://codecov.io/gh/sashirestela/cleverclient)
Expand All @@ -9,20 +9,26 @@ Library that makes it easy to use the Java HttpClient to perform http operations

### Table of Contents
- [Description](#-description)
- [How to Use](#-how-to-use)
- [Installation](#-installation)
- [Features](#-features)
- [CleverClient Builder](#cleverclient-builder)
- [Http Client Options](#http-client-options)
- [WebSocket Options](#websocket-options)
- [Interface Annotations](#interface-annotations)
- [Supported Response Types](#supported-response-types)
- [Interface Default Methods](#interface-default-methods)
- [Exception Handling](#exception-handling) **NEW**
- [Exception Handling](#exception-handling)
- [Examples](#-examples)
- [Contributing](#-contributing)
- [License](#-license)
- [Show Us Your Love](#-show-us-your-love)

## 💡 Description

CleverClient is a Java 11+ library that makes it easy to use the standard [HttpClient](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html) component to call http services by using annotated interfaces.
CleverClient is a Java library that simplifies requesting client-side Http services and websockets using annotated interfaces and methods. CleverClient uses behind the scenes two out-of-box Http client libraries: [Java's HttpClient](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html) (by default) or [Square's OkHttp](https://square.github.io/okhttp/) (adding a dependency).

## 📘 How to Use

For example, if we want to use the public API [JsonPlaceHolder](https://jsonplaceholder.typicode.com/) and call its endpoint ```/posts```, we just have to create an entity ```Post```, an interface ```PostService``` with special annotatons, and call the API through ```CleverClient```:

Expand Down Expand Up @@ -54,7 +60,7 @@ public interface PostService {

// Use CleverClient to call the API
var cleverClient = CleverClient.builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.baseUrl("https://jsonplaceholder.typicode.com")
.build();

var postService = cleverClient.create(PostService.class);
Expand Down Expand Up @@ -83,21 +89,28 @@ System.out.println(newPost);

## ⚙ Installation

You can install CleverClient by adding the following dependency to your Maven project:

You can install CleverClient by adding the following dependencies to your Maven project:
```xml
<dependency>
<groupId>io.github.sashirestela</groupId>
<artifactId>cleverclient</artifactId>
<version>[latest version]</version>
<version>[cleverclient_latest_version]</version>
</dependency>
<!-- OkHttp dependency is optional if you decide to use it with CleverClient -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>[okhttp_latest_version]</version>
</dependency>
```

Or alternatively using Gradle:

```groovy
dependencies {
implementation 'io.github.sashirestela:cleverclient:[latest version]'
implementation("io.github.sashirestela:cleverclient:[cleverclient_latest_version]")
/* OkHttp dependency is optional if you decide to use it with CleverClient */
implementation("com.squareup.okhttp3:okhttp:[okhttp_latest_version]")
}
```

Expand All @@ -109,19 +122,21 @@ Take in account that you need to use **Java 11 or greater**.

We have the following attributes to create a CleverClient object:

| Attribute | Description | Required |
| -------------------|---------------------------------------------------|-----------|
| baseUrl | Api's url | mandatory |
| headers | Map of headers (name/value) | optional |
| header | Single header as a name and a value | optional |
| httpClient | Java HttpClient object | optional |
| requestInterceptor | Function to modify the request once is built | optional |
| bodyInspector | Function to inspect the `@Body` request parameter | optional |
| endsOfStream | List of texts used to mark the end of streams | optional |
| endOfStream | Text used to mark the end of streams | optional |
| objectMapper | Provides Json conversions either to/from objects | optional |

The attribute ```end(s)OfStream``` is required when you have endpoints sending back streams of data (Server Sent Events - SSE).
| Attribute | Description | Required |
| -------------------|--------------------------------------------------------------|-----------|
| baseUrl | Api's url | mandatory |
| headers | Map of headers (name/value) | optional |
| header | Single header as a name and a value | optional |
| bodyInspector | Function to inspect the `@Body` request parameter | optional |
| requestInterceptor | Function to modify the request once is built | optional |
| responseInterceptor| Function to modify the response after it's received | optional |
| clientAdapter | Http client implementation (Java HttpClient or OkHttp based) | optional |
| webSocketAdapter | WebSocket implementation (Java HttpClient or OkHttp based) | optional |
| endsOfStream | List of texts used to mark the end of streams | optional |
| endOfStream | Text used to mark the end of streams | optional |
| objectMapper | Provides Json conversions either to/from objects | optional |

```end(s)OfStream``` is required when you have endpoints sending back streams of data (Server Sent Events - SSE).

Example:

Expand All @@ -145,18 +160,57 @@ var objectMapper = new ObjectMapper()
var cleverClient = CleverClient.builder()
.baseUrl(BASE_URL)
.header(HEADER_NAME, HEADER_VALUE)
.httpClient(httpClient)
.bodyInspector(body -> {
var validator = new Validator();
var violations = validator.validate(body);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
})
.requestInterceptor(request -> {
var url = request.getUrl();
url + (url.contains("?") ? "&" : "?") + "env=testing";
request.setUrl(url);
return request;
})
.responseInterceptor(response -> {
var modifiedBody = customProcessing(response.getBody());
response.setBody(modifiedBody);
return response;
})
.clientAdapter(new JavaHttpClientAdapter(httpClient))
.webSocketAdapter(new JavaHttpWebSocketAdapter(httpClient))
.endOfStream(END_OF_STREAM)
.objectMapper(objectMapper)
.build();
```

### Http Client Options

The Builder attribute ```clientAdapter``` determines which Http client implementation to use. CleverClient supports two implementations out of the box:
- Java's HttpClient (default) via ```JavaHttpClientAdapter```
- Square's OkHttp via ```OkHttpClientAdapter```

| clientAdapter's value | Description |
|-------------------------------------------------|-------------------------------------|
| new JavaHttpClientAdapter() | Uses a default Java's HttpClient |
| new JavaHttpClientAdapter(customJavaHttpClient) | Uses a custom Java's HttpClient |
| new OkHttpClientAdapter() | Uses a default OkHttpClient |
| new OkHttpClientAdapter(customOkHttpClient) | Uses a custom OkHttpClient |

### WebSocket Options

The Builder attribute ```webSocketAdapter``` lets you specify which WebSocket implementation to use. Similar to ```clientAdapter```, you can choose between:
- Java's HttpClient (default) via ```JavaHttpWebSocketAdapter```
- Square's OkHttp via ```OkHttpWebSocketAdapter```

| webSocketAdapter's value | Description |
|----------------------------------------------------|-------------------------------------|
| new JavaHttpWebSocketAdapter() | Uses a default Java's HttpClient |
| new JavaHttpWebSocketAdapter(customJavaHttpClient) | Uses a custom Java's HttpClient |
| new OkHttpWebSocketAdapter() | Uses a default OkHttpClient |
| new OkHttpWebSocketAdapter(customOkHttpClient) | Uses a custom OkHttpClient |

### Interface Annotations

| Annotation | Target | Attributes | Required Attrs | Mult |
Expand Down Expand Up @@ -337,12 +391,9 @@ Some examples have been created in the folder [example](https://github.com/sashi

Where:

* ```<className>``` is mandatory and must be one of the values:
* BasicExample
* FileDownloadExample
* HeaderExample
* MultiServiceExample
* StreamExample (This requires you have an OpenAI account and set the env variable OPENAI_API_TOKEN)
* ```<className>``` is mandatory and must be one of the Java files in the folder example: BasicExample, BasicExampleOkHttp, StreamExample, StreamExampleOkHttp, etc.

Some examples require you have an OpenAI account and set the env variable OPENAI_API_TOKEN, such as Multipart*, Stream*.

* ```[logOptions]``` are optional and you can you use them to set:
* Logger lever: ```-Dorg.slf4j.simpleLogger.defaultLogLevel=<logLevel>```
Expand All @@ -357,3 +408,10 @@ Please read our [Contributing](CONTRIBUTING.md) guide to learn and understand ho
CleverClient is licensed under the MIT License. See the
[LICENSE](https://github.com/sashirestela/cleverclient/blob/main/LICENSE) file
for more information.

## ❤ Show Us Your Love
Thanks for using **cleverclient**. If you find this project valuable there are a few ways you can show us your love, preferably all of them 🙂:

* Letting your friends know about this project 🗣📢.
* Writing a brief review on your social networks ✍🌐.
* Giving us a star on Github ⭐.
97 changes: 36 additions & 61 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

<groupId>io.github.sashirestela</groupId>
<artifactId>cleverclient</artifactId>
<version>1.6.3</version>
<version>2.0.0</version>
<packaging>jar</packaging>

<name>cleverclient</name>
<description>Java library that makes it easier to use the Java's HttpClient to perform http operations, using interfaces.</description>
<description>A Java library for making http client and websocket requests easily.</description>
<url>https://github.com/sashirestela/cleverclient</url>

<licenses>
Expand Down Expand Up @@ -55,6 +55,7 @@
<!-- Dependencies Versions -->
<lombok.version>1.18.36</lombok.version>
<jackson.version>2.18.2</jackson.version>
<okhttp.version>4.12.0</okhttp.version>
<slf4j.version>2.0.16</slf4j.version>
<junit.version>[5.11.0,6.0.0)</junit.version>
<mockito.version>[5.14.0,6.0.0)</mockito.version>
Expand All @@ -71,7 +72,7 @@
<javadoc.version>3.11.2</javadoc.version>
<gpg.version>3.2.7</gpg.version>
<sonatype.version>1.7.0</sonatype.version>
<spotless.version>2.43.0</spotless.version>
<spotless.version>2.44.2</spotless.version>
<dependency.version>3.8.1</dependency.version>
</properties>

Expand All @@ -85,6 +86,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<build>
Expand Down Expand Up @@ -196,91 +198,64 @@
</profile>
</profiles>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

Expand Down Expand Up @@ -404,4 +379,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
Loading
Loading