Skip to content

Commit

Permalink
Allows for configuring a custom ObjectMapper (#47)
Browse files Browse the repository at this point in the history
* Allow for configuring a custom ObjectMapper

This change modifies the OpaClient builder to optionally take a custom
ObjectMapper.
  • Loading branch information
nhrrsn authored Jul 25, 2022
1 parent 836a613 commit f2f4cdf
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
testImplementation("org.codehaus.groovy:groovy-all:2.5.15")
testImplementation("org.spockframework:spock-core:1.3-groovy-2.5")
testImplementation("com.github.tomakehurst:wiremock-jre8:2.31.0")
testImplementation("net.bytebuddy:byte-buddy:1.12.12")
}

repositories {
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/com/bisnode/opa/client/OpaClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
import com.bisnode.opa.client.query.QueryForDocumentRequest;
import com.bisnode.opa.client.rest.ObjectMapperFactory;
import com.bisnode.opa.client.rest.OpaRestClient;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.lang.reflect.ParameterizedType;
import java.net.http.HttpClient;
import java.util.Objects;
import java.util.Optional;

/**
* Opa client featuring {@link OpaDataApi}, {@link OpaQueryApi} and {@link OpaPolicyApi}
Expand Down Expand Up @@ -72,6 +74,7 @@ public void createOrUpdatePolicy(OpaPolicy policy) {
*/
public static class Builder {
private OpaConfiguration opaConfiguration;
private ObjectMapper objectMapper;

/**
* @param url URL including protocol and port
Expand All @@ -81,12 +84,19 @@ public Builder opaConfiguration(String url) {
return this;
}

public Builder objectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
return this;
}

public OpaClient build() {
Objects.requireNonNull(opaConfiguration, "build() called without opaConfiguration provided");
HttpClient httpClient = HttpClient.newBuilder()
.version(opaConfiguration.getHttpVersion())
.build();
OpaRestClient opaRestClient = new OpaRestClient(opaConfiguration, httpClient, ObjectMapperFactory.getInstance().create());
ObjectMapper objectMapper = Optional.ofNullable(this.objectMapper)
.orElseGet(ObjectMapperFactory.getInstance()::create);
OpaRestClient opaRestClient = new OpaRestClient(opaConfiguration, httpClient, objectMapper);
return new OpaClient(new OpaQueryClient(opaRestClient), new OpaDataClient(opaRestClient), new OpaPolicyClient(opaRestClient));
}
}
Expand Down
78 changes: 78 additions & 0 deletions src/test/groovy/com/bisnode/opa/client/OpaClientBuilderSpec.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.bisnode.opa.client


import com.bisnode.opa.client.query.QueryForDocumentRequest
import com.bisnode.opa.client.rest.ContentType
import com.fasterxml.jackson.databind.ObjectMapper
import com.github.tomakehurst.wiremock.WireMockServer
import spock.lang.Shared
import spock.lang.Specification

import static com.bisnode.opa.client.rest.ContentType.Values.APPLICATION_JSON
import static com.github.tomakehurst.wiremock.client.WireMock.*

class OpaClientBuilderSpec extends Specification {

private static int PORT = 8181
private static String url = "http://localhost:$PORT"

@Shared
private WireMockServer wireMockServer = new WireMockServer(PORT)

def setupSpec() {
wireMockServer.start()
}

def cleanupSpec() {
wireMockServer.stop()
}

def 'should configure OpaClient with custom ObjectMapper'() {

given:
def objectMapper = Spy(ObjectMapper)
def path = 'someDocument'
def endpoint = "/v1/data/$path"
wireMockServer
.stubFor(post(urlEqualTo(endpoint))
.withHeader(ContentType.HEADER_NAME, equalTo(APPLICATION_JSON))
.willReturn(aResponse()
.withStatus(200)
.withHeader(ContentType.HEADER_NAME, APPLICATION_JSON)
.withBody('{"result": {"authorized": true}}')))
def opaClient = OpaClient.builder()
.opaConfiguration(url)
.objectMapper(objectMapper)
.build();

when:
opaClient.queryForDocument(new QueryForDocumentRequest([shouldPass: true], path), Object.class)

then:
1 * objectMapper.writeValueAsString(_)
}

def 'should revert to default ObjectMapper if null ObjectMapper supplied'() {
given:
def path = 'someDocument'
def endpoint = "/v1/data/$path"
wireMockServer
.stubFor(post(urlEqualTo(endpoint))
.withHeader(ContentType.HEADER_NAME, equalTo(APPLICATION_JSON))
.willReturn(aResponse()
.withStatus(200)
.withHeader(ContentType.HEADER_NAME, APPLICATION_JSON)
.withBody('{"result": {"authorized": true}}')))
def opaClient = OpaClient.builder()
.opaConfiguration(url)
.objectMapper(null)
.build();

when:
def result = opaClient.queryForDocument(new QueryForDocumentRequest([shouldPass: true], path), Map.class)

then:
result != null
result.get("authorized") == true
}
}

0 comments on commit f2f4cdf

Please sign in to comment.