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

feat(java): Configuration overrides #189

Merged
merged 5 commits into from
Aug 24, 2023
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
4 changes: 4 additions & 0 deletions config/clients/java/config.overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/Configuration.java",
"templateType": "SupportingFiles"
},
"config-ConfigurationOverride.java.mustache" : {
"destinationFilename": "src/main/java/dev/openfga/sdk/api/client/ConfigurationOverride.java",
"templateType": "SupportingFiles"
},
"config-ConfigurationTest.java.mustache" : {
"destinationFilename": "src/test/java/dev/openfga/sdk/api/client/ConfigurationTest.java",
"templateType": "SupportingFiles"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import dev.openfga.sdk.errors.FgaInvalidParameterException;
import java.time.Duration;

public interface BaseConfiguration {
void assertValid() throws FgaInvalidParameterException;

String getApiUrl();

String getUserAgent();
Expand Down
43 changes: 36 additions & 7 deletions config/clients/java/template/config-Configuration.java.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import java.net.http.HttpClient;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpRequest;
import java.time.Duration;
import java.util.regex.Pattern;

/**
* Configurations for an ApiClient.
* Configurations for an api client.
*/
public class Configuration implements BaseConfiguration {
public static final String VERSION = "{{packageVersion}}";
Expand All @@ -29,6 +28,13 @@ public class Configuration implements BaseConfiguration {
private Duration readTimeout;
private Duration connectTimeout;

public Configuration() {
this.apiUrl = DEFAULT_API_URL;
this.userAgent = DEFAULT_USER_AGENT;
this.readTimeout = DEFAULT_READ_TIMEOUT;
this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
}

public Configuration(String apiUrl) {
this.apiUrl = apiUrl;
this.userAgent = DEFAULT_USER_AGENT;
Expand All @@ -39,7 +45,6 @@ public class Configuration implements BaseConfiguration {
/**
* Assert that the configuration is valid.
*/
@Override
public void assertValid() throws FgaInvalidParameterException {
// If apiUrl is null/empty/whitespace it will resolve to
// DEFAULT_API_URL when getApiUrl is called.
Expand All @@ -63,13 +68,37 @@ public class Configuration implements BaseConfiguration {
}
}

/**
* Construct a new {@link Configuration} with any non-null values of a {@link ConfigurationOverride} and remaining values from this {@link Configuration}.
*
* @param configurationOverride The values to override
* @return A new {@link Configuration} with values of this Configuration mixed with non-null values of configurationOverride
*/
public Configuration override(ConfigurationOverride configurationOverride) {
Configuration result = new Configuration();

String overrideApiUrl = configurationOverride.getApiUrl();
result.apiUrl(overrideApiUrl != null ? overrideApiUrl : apiUrl);

String overrideUserAgent = configurationOverride.getUserAgent();
result.userAgent(overrideUserAgent != null ? overrideUserAgent : userAgent);

Duration overrideReadTimeout = configurationOverride.getReadTimeout();
result.readTimeout(overrideReadTimeout != null ? overrideReadTimeout : readTimeout);

Duration overrideConnectTimeout = configurationOverride.getConnectTimeout();
result.connectTimeout(overrideConnectTimeout != null ? overrideConnectTimeout : connectTimeout);

return result;
}

/**
* Set the API URL for the http client.
*
* @param apiUrl The URL.
* @return This object.
*/
public BaseConfiguration apiUrl(String apiUrl) {
public Configuration apiUrl(String apiUrl) {
this.apiUrl = apiUrl;
return this;
}
Expand All @@ -94,7 +123,7 @@ public class Configuration implements BaseConfiguration {
* @param userAgent The user agent.
* @return This object.
*/
public BaseConfiguration userAgent(String userAgent) {
public Configuration userAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
Expand All @@ -120,7 +149,7 @@ public class Configuration implements BaseConfiguration {
* effectively infinite value.
* @return This object.
*/
public BaseConfiguration readTimeout(Duration readTimeout) {
public Configuration readTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
return this;
}
Expand Down Expand Up @@ -152,7 +181,7 @@ public class Configuration implements BaseConfiguration {
* @param connectTimeout connection timeout in milliseconds
* @return This object.
*/
public BaseConfiguration connectTimeout(Duration connectTimeout) {
public Configuration connectTimeout(Duration connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{{>licenseInfo}}
package {{invokerPackage}};

import java.net.http.HttpClient;
import java.net.http.HttpConnectTimeoutException;
import java.net.http.HttpRequest;
import java.time.Duration;

/**
* Configuration overrides for an api client. Values are initialized to null, and any values unset are intended to fall
* through to the values of a {@link Configuration}.
* <p>
* More details on intended usage of this class can be found in the documentation of the {@link Configuration#override(ConfigurationOverride)} method.
*/
public class ConfigurationOverride implements BaseConfiguration {
private String apiUrl;
private String userAgent;
private Duration readTimeout;
private Duration connectTimeout;

public ConfigurationOverride() {
this.apiUrl = null;
this.userAgent = null;
this.readTimeout = null;
this.connectTimeout = null;
}

/**
* Set the API URL for the http client.
*
* @param apiUrl The URL.
* @return This object.
*/
public ConfigurationOverride apiUrl(String apiUrl) {
this.apiUrl = apiUrl;
return this;
}

/**
* Get the API URL that was set.
*
* @return The url.
*/
@Override
public String getApiUrl() {
return apiUrl;
}

/**
* Set the user agent.
*
* @param userAgent The user agent.
* @return This object.
*/
public ConfigurationOverride userAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}

/**
* Get the user agent.
*
* @return The user agent.
*/
@Override
public String getUserAgent() {
return userAgent;
}

/**
* Set the read timeout for the http client.
*
* <p>This is the value used by default for each request, though it can be
* overridden on a per-request basis with a request interceptor.</p>
*
* @param readTimeout The read timeout used by default by the http client.
* Setting this value to null resets the timeout to an
* effectively infinite value.
* @return This object.
*/
public ConfigurationOverride readTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
return this;
}

/**
* Get the read timeout that was set.
*
* @return The read timeout, or null if no timeout was set. Null represents
* an infinite wait time.
*/
@Override
public Duration getReadTimeout() {
return readTimeout;
}

/**
* Sets the connect timeout (in milliseconds) for the http client.
*
* <p> In the case where a new connection needs to be established, if
* the connection cannot be established within the given {@code
* duration}, then {@link HttpClient#send(HttpRequest, BodyHandler)
* HttpClient::send} throws an {@link HttpConnectTimeoutException}, or
* {@link HttpClient#sendAsync(HttpRequest, BodyHandler)
* HttpClient::sendAsync} completes exceptionally with an
* {@code HttpConnectTimeoutException}. If a new connection does not
* need to be established, for example if a connection can be reused
* from a previous request, then this timeout duration has no effect.
*
* @param connectTimeout connection timeout in milliseconds
* @return This object.
*/
public ConfigurationOverride connectTimeout(Duration connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}

/**
* Get connection timeout (in milliseconds).
*
* @return Timeout in milliseconds
*/
@Override
public Duration getConnectTimeout() {
return connectTimeout;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import static org.junit.jupiter.api.Assertions.*;

import dev.openfga.sdk.errors.*;
import org.junit.jupiter.api.Test;
import java.time.Duration;

class ConfigurationTest {
private static final String DEFAULT_API_URL = "http://localhost:8080";
private static final String DEFAULT_USER_AGENT = "{{{userAgent}}}";
private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(10);
private static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofSeconds(10);

@Test
void apiUrl_nullDefaults() throws FgaInvalidParameterException {
// Given
Expand Down Expand Up @@ -47,41 +53,132 @@ class ConfigurationTest {

@Test
void apiUrl_stringNoProtocolFails() {
// Given
String apiUrl = "localhost:8080";

// When
FgaInvalidParameterException e = assertThrows(FgaInvalidParameterException.class, () -> {
var config = new Configuration(apiUrl);
config.assertValid();
});

// Then
assertEquals("Required parameter apiUrl was invalid when calling Configuration.", e.getMessage());
}

@Test
void apiUrl_stringInvalidProtocolFails() {
// Given
String apiUrl = "zzz://localhost:8080";

// When
FgaInvalidParameterException e = assertThrows(FgaInvalidParameterException.class, () -> {
var config = new Configuration(apiUrl);
config.assertValid();
});

// Then
assertEquals("Required parameter apiUrl was invalid when calling Configuration.", e.getMessage());
}

@Test
void apiUrl_stringNoHostFails() {
// Given
String apiUrl = "http://";

// When
FgaInvalidParameterException e = assertThrows(FgaInvalidParameterException.class, () -> {
var config = new Configuration(apiUrl);
config.assertValid();
});

// Then
assertEquals("Required parameter apiUrl was invalid when calling Configuration.", e.getMessage());
}

@Test
void apiUrl_stringBadPortFails() {
String apiUrl = "http://localshost:abcd";
// Given
String apiUrl = "http://localhost:abcd";

// When
FgaInvalidParameterException e = assertThrows(FgaInvalidParameterException.class, () -> {
var config = new Configuration(apiUrl);
config.assertValid();
});

// Then
assertEquals("Required parameter apiUrl was invalid when calling Configuration.", e.getMessage());
}

@Test
void defaults() {
// Given
Configuration config = new Configuration();

// NOTE: Failures in this test indicate that default values in Configuration have changed. Changing
// the defaults of Configuration can be a suprising and breaking change for consumers.

// Then
assertEquals(DEFAULT_API_URL, config.getApiUrl());
assertEquals(DEFAULT_USER_AGENT, config.getUserAgent());
assertEquals(DEFAULT_READ_TIMEOUT, config.getReadTimeout());
assertEquals(DEFAULT_CONNECT_TIMEOUT, config.getConnectTimeout());
}

@Test
void override_apiUrl() {
// Given
Configuration original = new Configuration();
ConfigurationOverride configOverride = new ConfigurationOverride().apiUrl("https://override.url");

// When
Configuration result = original.override(configOverride);

// Then
assertEquals("https://override.url", result.getApiUrl());
assertEquals(DEFAULT_API_URL, original.getApiUrl(), "The Configuration's default apiUrl should be unmodified.");
}

@Test
void override_userAgent() {
// Given
Configuration original = new Configuration();
ConfigurationOverride configOverride = new ConfigurationOverride().userAgent("override-agent");

// When
Configuration result = original.override(configOverride);

// Then
assertEquals("override-agent", result.getUserAgent());
assertEquals(DEFAULT_USER_AGENT, original.getUserAgent(), "The Configuration's default userAgent should be unmodified.");
}

@Test
void override_readTimeout() {
// Given
Configuration original = new Configuration();
ConfigurationOverride configOverride = new ConfigurationOverride().readTimeout(Duration.ofDays(7));

// When
Configuration result = original.override(configOverride);

// Then
assertEquals(Duration.ofDays(7), result.getReadTimeout());
assertEquals(DEFAULT_READ_TIMEOUT, original.getReadTimeout(), "The Configuration's default readTimeout should be unmodified.");
}

@Test
void override_connectTimeout() {
// Given
Configuration original = new Configuration();
ConfigurationOverride configOverride = new ConfigurationOverride().connectTimeout(Duration.ofDays(7));

// When
Configuration result = original.override(configOverride);

// Then
assertEquals(Duration.ofDays(7), result.getConnectTimeout());
assertEquals(DEFAULT_CONNECT_TIMEOUT, original.getConnectTimeout(), "The Configuration's default connectTimeout should be unmodified.");
}
}
Loading
Loading