Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
78 changes: 13 additions & 65 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# Java
# Java build files
*.class
*.jar
*.war
*.ear
*.nar
hs_err_pid*
replay_pid*

# Maven
target/
Expand All @@ -16,78 +13,29 @@ pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar

# Gradle
bin/
# Gradle (if applicable)
.gradle/
build/
.gradle
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar
!gradle/wrapper/gradle-wrapper.jar

# Eclipse
.settings/
.classpath
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.loadpath
.factorypath
.recommenders/
.apt_generated/
.apt_generated_test/

# VSCode
.vscode/
.code-workspace
.history/
.ionide/

# IntelliJ (included just in case)
# IntelliJ IDEA
.idea/
*.iml
*.iws
*.ipr
*.iws
out/
.idea_modules/

# NetBeans (included just in case)
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
# Eclipse
.classpath
.project
.settings/

# OS specific
# VS Code
.vscode/

# OS files
.DS_Store
Thumbs.db
ehthumbs.db
Desktop.ini

# Logs
*.log
log/
logs/

# Environment files
.env
.env.local
.env.*
!.env.example

# Application specific
/src/main/resources/application-*.properties
/src/main/resources/application-*.yml
/src/main/resources/application-*.yaml
!/src/main/resources/application.properties
!/src/main/resources/application.yml
!/src/main/resources/application.yaml
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>io.github.odunlamizo</groupId>
<artifactId>java-jsonbin</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<name>java-paystack</name>
<url>http://maven.apache.org</url>

<!-- <url>http://maven.apache.org</url>-->

<properties>
<java.version>17</java.version>
Expand Down Expand Up @@ -101,6 +105,7 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/github/odunlamizo/jsonbin/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static void main(String[] args) {
// Load environment variables from .env file
Dotenv dotenv = Dotenv.configure().load();

// Get master key from .env
// Get the master key from .env
String masterKey = dotenv.get("JSONBIN_MASTER_KEY");

// Check if the master key exists
Expand All @@ -20,8 +20,8 @@ public static void main(String[] args) {
System.exit(1);
}

var jsonBin = new JsonBinOkHttp.Builder().withMasterKey(masterKey).build(UserList.class);
Bin<UserList> bin = jsonBin.readBin("687644d36063391d31ae163f");
JsonBin jsonBin = new JsonBinOkHttp.Builder().withMasterKey(masterKey).build();
Bin<UserList> bin = jsonBin.readBin("687644d36063391d31ae163f", UserList.class);
System.out.println(bin);
}
}
6 changes: 4 additions & 2 deletions src/main/java/io/github/odunlamizo/jsonbin/JsonBin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import lombok.NonNull;

/** JSONBin.io Java SDK */
public interface JsonBin<T> {
public interface JsonBin {

/**
* Reads the contents of a bin from JSONBin.io using its unique identifier.
Expand All @@ -13,8 +13,10 @@ public interface JsonBin<T> {
* strongly-typed {@link Bin} object containing the expected data type {@code T}.
*
* @param binId the unique identifier of the bin to retrieve; must not be {@code null}
* @param recordClass the class of the expected record type {@code T} used for deserialization;
* must not be {@code null}
* @return a {@link Bin} object containing the deserialized data
* @throws JsonBinException if the request fails, the bin is not found, or deserialization fails
*/
Bin<T> readBin(@NonNull String binId) throws JsonBinException;
<T> Bin<T> readBin(@NonNull String binId, Class<T> recordClass) throws JsonBinException;
}
2 changes: 1 addition & 1 deletion src/main/java/io/github/odunlamizo/jsonbin/model/Bin.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import lombok.ToString;

/**
* Represents a response wrapper from JSONBin.io containing both the data record and its metadata.
* Represents a response wrapper from JSONBIN.io containing both the data record and its metadata.
*
* <p>This generic class is used to hold the actual data stored in the bin (as {@code record}) and
* additional information about the bin such as creation time, visibility, and name (as {@link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import lombok.ToString;

/**
* Represents metadata information returned from a JSONBin.io response.
* Represents metadata information returned from a JSONBIN.io response.
*
* <p>This includes details such as the bin's unique identifier, visibility, creation timestamp, and
* assigned name.
Expand Down Expand Up @@ -46,7 +46,7 @@ public class Metadata {
/**
* The unique identifier of the collection this bin belongs to.
*
* <p>This ID is used to associate the bin with a specific collection in JSONBin.io.
* <p>This ID is used to associate the bin with a specific collection in JSONBIN.io.
*/
private String collectionId;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.odunlamizo.jsonbin.okhttp;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.github.odunlamizo.jsonbin.JsonBin;
Expand All @@ -9,26 +8,18 @@
import io.github.odunlamizo.jsonbin.model.Error;
import io.github.odunlamizo.jsonbin.util.JsonUtil;
import java.io.IOException;
import java.util.Objects;
import java.util.function.Function;
import lombok.NonNull;
import okhttp3.OkHttpClient;
import okhttp3.Request;

/** JSONBin.io Java SDK implementation powered by OkHttp */
public class JsonBinOkHttp<T> implements JsonBin<T> {
/** JSONBIN.io Java SDK implementation powered by OkHttp */
public class JsonBinOkHttp implements JsonBin {

private final OkHttpClient client;
private final String baseUrl;
private final Function<String, Bin<T>> deserializer;

private JsonBinOkHttp(
String masterKey,
String accessKey,
String baseUrl,
Function<String, Bin<T>> deserializer) {
private JsonBinOkHttp(String masterKey, String accessKey, String baseUrl) {
this.baseUrl = baseUrl;
this.deserializer = deserializer;
this.client =
new OkHttpClient.Builder()
.addInterceptor(new AuthInterceptor(masterKey, accessKey))
Expand Down Expand Up @@ -57,60 +48,52 @@ public Builder withBaseUrl(String baseUrl) {
return this;
}

public <T> JsonBinOkHttp<T> build(Class<T> recordClass) {
public JsonBinOkHttp build() {
if ((masterKey == null || masterKey.isBlank())
&& (accessKey == null || accessKey.isBlank())) {
throw new IllegalArgumentException(
"Either masterKey or accessKey must be provided.");
}

return new JsonBinOkHttp<>(
masterKey,
accessKey,
baseUrl,
json -> {
TypeReference<Bin<T>> ref =
new TypeReference<>() {
@Override
public java.lang.reflect.Type getType() {
return TypeFactory.defaultInstance()
.constructParametricType(Bin.class, recordClass);
}
};
try {
return JsonUtil.toValue(json, ref);
} catch (JsonProcessingException exception) {
throw new JsonBinException(
exception.getMessage(), exception.getCause());
}
});
return new JsonBinOkHttp(masterKey, accessKey, baseUrl);
}
}

@Override
public Bin<T> readBin(@NonNull String binId) throws JsonBinException {
public <T> Bin<T> readBin(@NonNull String binId, Class<T> recordClass) throws JsonBinException {
final String URL = String.format("%s/b/%s", baseUrl, binId);
Request request = new Request.Builder().url(URL).build();

return newCall(request);
return newCall(request, recordClass);
}

private Bin<T> newCall(Request request) {
private <T> Bin<T> newCall(Request request, Class<T> recordClass) {
try (okhttp3.Response response = client.newCall(request).execute()) {

if (Objects.isNull(response.body())) {
if (response.body() == null) {
throw new JsonBinException("Response body is null");
}

String json = response.body().string();

if (!response.isSuccessful()) {
Error errorResponse = JsonUtil.toValue(json, new TypeReference<Error>() {});
throw new JsonBinException(errorResponse.getMessage());
Error error = JsonUtil.toValue(json, new TypeReference<Error>() {});
throw new JsonBinException(error.getMessage());
}

return deserializer.apply(json);
} catch (IOException exception) {
throw new JsonBinException(exception.getMessage(), exception.getCause());
TypeReference<Bin<T>> ref =
new TypeReference<>() {
@Override
public java.lang.reflect.Type getType() {
return TypeFactory.defaultInstance()
.constructParametricType(Bin.class, recordClass);
}
};

return JsonUtil.toValue(json, ref);

} catch (IOException e) {
throw new JsonBinException(e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.jupiter.api.Assertions.*;

import io.github.odunlamizo.jsonbin.JsonBin;
import io.github.odunlamizo.jsonbin.JsonBinException;
import io.github.odunlamizo.jsonbin.model.Bin;
import io.github.odunlamizo.jsonbin.model.User;
Expand Down Expand Up @@ -55,13 +56,10 @@ void shouldDeserializeValidBinResponse() {

String mockUrl = mockWebServer.url("").toString().replaceAll("/$", "");

JsonBinOkHttp<UserList> jsonBin =
new JsonBinOkHttp.Builder()
.withMasterKey("dummy-key")
.withBaseUrl(mockUrl)
.build(UserList.class);
JsonBin jsonBin =
new JsonBinOkHttp.Builder().withMasterKey("dummy-key").withBaseUrl(mockUrl).build();

Bin<UserList> result = jsonBin.readBin("test-bin-id");
Bin<UserList> result = jsonBin.readBin("test-bin-id", UserList.class);

assertNotNull(result);
assertEquals("abc123", result.getMetadata().getId());
Expand Down Expand Up @@ -89,14 +87,13 @@ void shouldThrowExceptionOnErrorResponse() {

String mockUrl = mockWebServer.url("").toString().replaceAll("/$", "");

JsonBinOkHttp<UserList> jsonBin =
new JsonBinOkHttp.Builder()
.withMasterKey("dummy-key")
.withBaseUrl(mockUrl)
.build(UserList.class);
JsonBin jsonBin =
new JsonBinOkHttp.Builder().withMasterKey("dummy-key").withBaseUrl(mockUrl).build();

JsonBinException exception =
assertThrows(JsonBinException.class, () -> jsonBin.readBin("invalid-id"));
assertThrows(
JsonBinException.class,
() -> jsonBin.readBin("invalid-id", UserList.class));

assertTrue(exception.getMessage().contains("Bin not found"));
}
Expand Down