Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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