Skip to content

Commit 065f863

Browse files
Merge pull request #1 from reSMS-dev/feat/SMS-100_abstract_http_client
feat: add the httpClient structure
2 parents 2c56093 + 9790711 commit 065f863

8 files changed

Lines changed: 227 additions & 0 deletions

File tree

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<lombok.version>1.18.38</lombok.version>
6262
<maven.compiler.plugin.version>3.14.0</maven.compiler.plugin.version>
6363
<moshi.version>1.15.2</moshi.version>
64+
<okhttp.version>4.12.0</okhttp.version>
6465
</properties>
6566

6667
<dependencies>
@@ -69,6 +70,11 @@
6970
<artifactId>moshi</artifactId>
7071
<version>${moshi.version}</version>
7172
</dependency>
73+
<dependency>
74+
<groupId>com.squareup.okhttp3</groupId>
75+
<artifactId>okhttp</artifactId>
76+
<version>${okhttp.version}</version>
77+
</dependency>
7278
<dependency>
7379
<groupId>org.apache.httpcomponents.core5</groupId>
7480
<artifactId>httpcore5</artifactId>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dev.resms.core.mapper;
2+
3+
/** An interface for mapping between JSON representation and Java objects using Moshi. */
4+
public interface IMapper {
5+
6+
/**
7+
* Converts the provided object into its JSON representation.
8+
*
9+
* @param object The object to be converted to JSON.
10+
* @return The JSON representation of the object.
11+
*/
12+
String toJson(Object object);
13+
14+
/**
15+
* Converts the provided JSON value into an instance of the specified class.
16+
*
17+
* @param value The JSON value to be converted.
18+
* @param clazz The class to convert the JSON value to.
19+
* @param <T> The type of the resulting object.
20+
* @return An instance of the specified class with values from the JSON value.
21+
*/
22+
<T> T fromJson(String value, Class<T> clazz);
23+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package dev.resms.core.mapper;
2+
3+
import com.squareup.moshi.Moshi;
4+
import java.io.IOException;
5+
6+
/**
7+
* Implementation of the IMapper interface for mapping between JSON representation and Java objects
8+
* using Moshi.
9+
*/
10+
public class ReSMSMapper implements IMapper {
11+
12+
private final Moshi moshi;
13+
14+
public ReSMSMapper() {
15+
this.moshi = new Moshi.Builder().build();
16+
}
17+
18+
/**
19+
* Converts the provided object into its JSON representation.
20+
*
21+
* @param object The object to be converted to JSON.
22+
* @return The JSON representation of the object.
23+
*/
24+
@Override
25+
public String toJson(Object object) {
26+
return moshi.adapter(Object.class).toJson(object);
27+
}
28+
29+
/**
30+
* Converts the provided JSON value into an instance of the specified class.
31+
*
32+
* @param value The JSON value to be converted.
33+
* @param clazz The class to convert the JSON value to.
34+
* @param <T> The type of the resulting object.
35+
* @return An instance of the specified class with values from the JSON value.
36+
*/
37+
@Override
38+
public <T> T fromJson(String value, Class<T> clazz) {
39+
try {
40+
return moshi.adapter(clazz).fromJson(value);
41+
} catch (IOException e) {
42+
e.printStackTrace();
43+
return null;
44+
}
45+
}
46+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dev.resms.core.net;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
/**
8+
* Represents an HTTP response containing the response code, body, and success status.
9+
*
10+
* @param <T> The type of the response body.
11+
*/
12+
@Getter
13+
@Setter
14+
@AllArgsConstructor
15+
public class AbstractHttpResponse<T> {
16+
17+
/** The HTTP response code. */
18+
private int code;
19+
20+
/** The response body. */
21+
private T body;
22+
23+
/** Indicates whether the HTTP request was successful. */
24+
private boolean isSuccessful;
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.resms.core.net;
2+
3+
/** An enumeration representing common HTTP methods. */
4+
public enum HttpMethod {
5+
GET,
6+
POST,
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dev.resms.core.net;
2+
3+
/**
4+
* An interface representing an HTTP client for performing HTTP requests and receiving responses.
5+
*
6+
* @param <T> The type of response data expected.
7+
*/
8+
public interface IHttpClient<T> {
9+
10+
/**
11+
* Perform an HTTP request with the specified path, method, and payload.
12+
*
13+
* @param path The path or endpoint of the request.
14+
* @param apiKey The API Key used to authenticate the request.
15+
* @param method The HTTP method (GET, POST, PUT, DELETE, etc.).
16+
* @param payload The payload or data to send with the request.
17+
* @return An {@link AbstractHttpResponse} representing the response from the server.
18+
*/
19+
AbstractHttpResponse<T> perform(
20+
final String path, final String apiKey, final HttpMethod method, final String payload);
21+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dev.resms.core.net.impl;
2+
3+
import dev.resms.core.net.AbstractHttpResponse;
4+
import dev.resms.core.net.HttpMethod;
5+
import dev.resms.core.net.IHttpClient;
6+
import java.io.IOException;
7+
import okhttp3.MediaType;
8+
import okhttp3.OkHttpClient;
9+
import okhttp3.Request;
10+
import okhttp3.RequestBody;
11+
import okhttp3.Response;
12+
13+
/**
14+
* An implementation of the {@link IHttpClient} interface for performing HTTP requests. This
15+
* implementation uses the OkHttp library for handling HTTP communication.
16+
*/
17+
public class HttpClient implements IHttpClient<Response> {
18+
19+
/** The base URL for the API. */
20+
public static final String BASE_API = "https://api.resms.dev/";
21+
22+
/** The OkHttpClient instance for handling HTTP requests. */
23+
private final OkHttpClient httpClient;
24+
25+
/** Constructs an instance of the HttpClient. */
26+
public HttpClient() {
27+
this.httpClient = new OkHttpClient();
28+
}
29+
30+
/**
31+
* Performs an HTTP request with the specified path, HTTP method, and payload.
32+
*
33+
* @param path The path or endpoint of the request.
34+
* @param apiKey The API Key used to authenticate the request.
35+
* @param method The HTTP method (GET, POST, PUT, DELETE, etc.).
36+
* @param payload The payload or data to send with the request.
37+
* @return An {@link AbstractHttpResponse} representing the response from the server.
38+
*/
39+
@Override
40+
public AbstractHttpResponse<Response> perform(
41+
final String path, final String apiKey, final HttpMethod method, final String payload) {
42+
43+
RequestBody requestBody = null;
44+
if (payload != null) {
45+
requestBody = RequestBody.create(payload, MediaType.get("application/json"));
46+
}
47+
48+
Request request =
49+
new Request.Builder()
50+
.url(BASE_API + path)
51+
.addHeader("Accept", "application/json")
52+
.addHeader("X-Api-Key", apiKey)
53+
.method(method.name(), requestBody)
54+
.build();
55+
56+
try {
57+
Response response = httpClient.newCall(request).execute();
58+
return new AbstractHttpResponse(
59+
response.code(), response.body().string(), response.isSuccessful());
60+
} catch (IOException e) {
61+
throw new RuntimeException(e);
62+
}
63+
}
64+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package dev.resms.core.service;
2+
3+
import dev.resms.core.mapper.ReSMSMapper;
4+
import dev.resms.core.net.IHttpClient;
5+
import dev.resms.core.net.impl.HttpClient;
6+
import lombok.Getter;
7+
8+
/**
9+
* An abstract base class for service implementations, providing common functionality such as HTTP
10+
* client, authentication provider, and mapper initialization.
11+
*/
12+
@Getter
13+
public abstract class BaseService {
14+
15+
/** Apikey used for authenticating requests. */
16+
protected final String apiKey;
17+
18+
/** HTTP client for making HTTP requests. */
19+
protected final IHttpClient httpClient;
20+
21+
/** Mapper responsible for mapping data between different representations. */
22+
protected final ReSMSMapper reSMSMapper;
23+
24+
/**
25+
* Constructs a BaseService instance with the specified authentication provider, default HTTP
26+
* client, and mapper.
27+
*
28+
* @param apiKey The apiKey to use.
29+
*/
30+
protected BaseService(final String apiKey) {
31+
this.apiKey = apiKey;
32+
this.httpClient = new HttpClient();
33+
this.reSMSMapper = new ReSMSMapper();
34+
}
35+
}

0 commit comments

Comments
 (0)