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
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ switcher.domain -> Domain name
#optional
switcher.environment -> Environment name
switcher.offline -> true/false When offline, it will only use a local snapshot file
switcher.snapshot.file -> Snapshot file path
switcher.snapshot.location -> Folder from where snapshots will be saved/read
switcher.snapshot.auto -> true/false Automated lookup for snapshot when loading the application
switcher.snapshot.skipvalidation -> true/false Skip snapshotValidation() that can be used for UT executions
Expand Down Expand Up @@ -183,8 +182,8 @@ switcher.throttle(1000).isItOn();
```

## Offline settings
You can also force the Switcher library to work offline. In this case, the snapshot location must be set up, so the context can be re-built using the offline configuration.
Or you can just configure the Client SDK using the properties file.
You can also set the Switcher library to work offline. It will use a local snapshot file to retrieve the switchers configuration.<br>
This feature is useful for testing purposes or when you need to run your application without internet access.

```java
MyAppFeatures.configure(ContextBuilder.builder()
Expand All @@ -199,9 +198,8 @@ switcher.isItOn();


## Real-time snapshot updater
Let the Switcher Client manage your application local snapshot file.

In order to minimize roundtrips and unnecessary file parsing, try to use one of these features to improve the overall performance when accessing snapshots locally.
Let the Switcher Client manage your application local snapshot.<br>
These features allow you to configure the SDK to automatically update the snapshot in the background.

1. This feature will update the in-memory Snapshot every time the file is modified.

Expand All @@ -210,17 +208,16 @@ MyAppFeatures.watchSnapshot();
MyAppFeatures.stopWatchingSnapshot();
```

2. You can also perform snapshot update validation to verify if there are changes to be pulled. This will ensure that your application is running the most recent version of your remote configuration.
2. You can also perform snapshot update validation to verify if there are changes to be pulled.

```java
MyAppFeatures.validateSnapshot();
```

3. Enable the Client SDK to execute Snapshot Auto Updates in the background using configuration. It basically encapsulates the validateSnapshot feature into a scheduled task managed by the SDK.
It requires to set either snapshotFile or snapshotLocation.

```java
// It will check and update the local/in-memory snapshot to the latest version
// It will check and update the local/in-memory snapshot to the latest version every second
MyAppFeatures.configure(ContextBuilder.builder()
.snapshotAutoUpdateInterval("1s")
.snapshotLocation("/src/resources"));
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<groupId>com.github.switcherapi</groupId>
<artifactId>switcher-client</artifactId>
<packaging>jar</packaging>
<version>2.0.3</version>
<version>2.0.4-SNAPSHOT</version>

<name>Switcher Client</name>
<description>Switcher Client SDK for working with Switcher API</description>
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/com/github/switcherapi/client/ContextBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ public ContextBuilder snapshotLocation(String snapshotLocation) {
return this;
}

public ContextBuilder snapshotFile(String snapshotFile) {
properties.setSnapshotFile(snapshotFile);
return this;
}

public ContextBuilder snapshotAutoUpdateInterval(String snapshotAutoUpdateInterval) {
properties.setSnapshotAutoUpdateInterval(snapshotAutoUpdateInterval);

if (snapshotAutoUpdateInterval != null)
properties.setSnapshotAutoLoad(true);

return this;
}

Expand All @@ -102,6 +101,10 @@ public ContextBuilder snapshotSkipValidation(boolean snapshotSkipValidation) {

public ContextBuilder silentMode(boolean silentMode) {
properties.setSilentMode(silentMode);

if (silentMode)
properties.setSnapshotAutoLoad(true);

return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.github.switcherapi.client;

import java.io.File;

import com.github.switcherapi.client.exception.SwitcherContextException;
import com.github.switcherapi.client.model.ContextKey;
import org.apache.commons.lang3.StringUtils;

import com.github.switcherapi.client.exception.SwitcherContextException;

/**
* Helper class to validate SwitcherProperties parameters
*
Expand All @@ -15,12 +12,7 @@
*/
class SwitcherContextValidator {

private static final String SNAPSHOT_PATH_PATTERN = "%s/%s.json";
public static final String ERR_FORMAT = "Invalid parameter format for [%s]. Expected %s.";
public static final String ERR_LOCATION_SNAPSHOT_FILE = "Snapshot locations not defined [add: switcher.snapshot.location or switcher.snapshot.file]";
public static final String ERR_SNAPSHOT_FILE = "Snapshot file not defined [add: switcher.snapshot.file]";
public static final String ERR_SNAPSHOT_LOCATION = "Snapshot location not defined [add: switcher.snapshot.location]";
public static final String ERR_SNAPSHOT_AUTO_UPDATE = "Snapshot Update Interval requires [switcher.url, switcher.snapshot.file/location]";
public static final String ERR_RETRY = "Retry not defined [add: switcher.retry]";
public static final String ERR_URL = "URL not defined [add: switcher.url]";
public static final String ERR_API = "API Key not defined [add: switcher.apikey]";
Expand All @@ -43,75 +35,21 @@ public static void validate(final SwitcherProperties prop) {

if (!prop.isOfflineMode()) {
validateOnline(prop);
} else {
validateOffline(prop);
}

validateOptionals(prop);
}

/**
* Validate Offline settings
*
* @param prop Configured properties
*/
public static void validateOffline(final SwitcherProperties prop) {
final StringBuilder error = new StringBuilder();

// No Snapshot File may require a Snapshot Location
if (StringUtils.isBlank(prop.getSnapshotFile())) {
error.append(ERR_LOCATION_SNAPSHOT_FILE);
} else {
final File file = new File(prop.getSnapshotFile());
if (!file.exists()) {
throw new SwitcherContextException(ERR_SNAPSHOT_FILE);
} else {
return;
}
}

// No Snapshot Location may require Snapshot File
if (StringUtils.isBlank(prop.getSnapshotLocation())) {
if (!StringUtils.isBlank(error.toString())) {
throw new SwitcherContextException(error.toString());
}

// Snapshot Autoload requires a valid Snapshot Location
} else if (!prop.isSnapshotAutoLoad()) {
final File folderPath = new File(prop.getSnapshotLocation());
if (!folderPath.exists()) {
throw new SwitcherContextException(ERR_SNAPSHOT_LOCATION);
} else {
final File snapshotFile = new File(
String.format(SNAPSHOT_PATH_PATTERN, prop.getSnapshotLocation(), prop.getEnvironment()));

if (!snapshotFile.exists()) {
throw new SwitcherContextException(ERR_SNAPSHOT_LOCATION);
}
}
}
}

/**
* Validate optional context arguments
*
* @param prop Configured properties
*/
public static void validateOptionals(final SwitcherProperties prop) {
if (prop.isSnapshotAutoLoad() && StringUtils.isBlank(prop.getSnapshotLocation())) {
throw new SwitcherContextException(ERR_SNAPSHOT_LOCATION);
}

if (prop.isSilentMode() && StringUtils.isBlank(prop.getRetryAfter())) {
throw new SwitcherContextException(ERR_RETRY);
}

if (!StringUtils.isBlank(prop.getSnapshotAutoUpdateInterval()) &&
(StringUtils.isBlank(StringUtils.defaultIfEmpty(prop.getSnapshotLocation(), StringUtils.EMPTY) +
StringUtils.defaultIfEmpty(prop.getSnapshotFile(), StringUtils.EMPTY)))) {
throw new SwitcherContextException(ERR_SNAPSHOT_AUTO_UPDATE);
}

try {
Integer.parseInt(prop.getRegexTimeout());
} catch (NumberFormatException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,11 @@ protected Domain initializeSnapshotFromAPI() {

try {
final Snapshot snapshot = ClientRemoteService.getInstance().resolveSnapshot();
SnapshotLoader.saveSnapshot(snapshot,
SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_LOCATION),
environment);
final String snapshotLocation = SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_LOCATION);

if (snapshotLocation != null) {
SnapshotLoader.saveSnapshot(snapshot, snapshotLocation, environment);
}

return snapshot.getDomain();
} catch (SwitcherRemoteException | SwitcherSnapshotWriteException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ class SwitcherProperties {

private String snapshotLocation;

private String snapshotFile;

private String snapshotAutoUpdateInterval;

private String retryAfter;
Expand Down Expand Up @@ -67,7 +65,6 @@ public void loadFromProperties(Properties prop) {
setDomain(SwitcherUtils.resolveProperties(ContextKey.DOMAIN.getParam(), prop));
setComponent(SwitcherUtils.resolveProperties(ContextKey.COMPONENT.getParam(), prop));
setEnvironment(SwitcherUtils.resolveProperties(ContextKey.ENVIRONMENT.getParam(), prop));
setSnapshotFile(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_FILE.getParam(), prop));
setSnapshotLocation(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_LOCATION.getParam(), prop));
setSnapshotSkipValidation(Boolean.parseBoolean(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_SKIP_VALIDATION.getParam(), prop)));
setSnapshotAutoLoad(Boolean.parseBoolean(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_AUTO_LOAD.getParam(), prop)));
Expand Down Expand Up @@ -148,14 +145,6 @@ public void setSnapshotLocation(String snapshotLocation) {
this.snapshotLocation = snapshotLocation;
}

public String getSnapshotFile() {
return snapshotFile;
}

public void setSnapshotFile(String snapshotFile) {
this.snapshotFile = snapshotFile;
}

public String getSnapshotAutoUpdateInterval() {
return snapshotAutoUpdateInterval;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ public enum ContextKey {
*/
ENVIRONMENT("switcher.environment", "environment"),

/**
* (String) The absolute path of the snapshot file, including the file's name.
*/
SNAPSHOT_FILE("switcher.snapshot.file", "snapshotFile"),

/**
* (String) Folder path where all snapshot files are located.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
* @since 2019-12-24
*/
public interface ClientWS {


Integer DEFAULT_TIMEOUT_SECONDS = 3;
String HEADER_AUTHORIZATION = "Authorization";
String HEADER_APIKEY = "switcher-api-key";
String TOKEN_TEXT = "Bearer %s";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
* @author Roger Floriano (petruki)
Expand All @@ -40,7 +41,9 @@ public class ClientWSImpl implements ClientWS {
private final Client client;

public ClientWSImpl() {
this.client = ClientWSBuilder.builder().build();
this.client = ClientWSBuilder.builder()
.connectTimeout(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@ public SwitcherLocalService() {
* @throws SwitcherSnapshotLoadException in case it was not possible to load snapshot automatically
*/
public void init() {
final String snapshotFile = SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_FILE);
final String snapshotLocation = SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_LOCATION);
final String environment = SwitcherContextBase.contextStr(ContextKey.ENVIRONMENT);
final boolean snapshotAutoload = SwitcherContextBase.contextBol(ContextKey.SNAPSHOT_AUTO_LOAD);

if (StringUtils.isNotBlank(snapshotFile)) {
this.domain = SnapshotLoader.loadSnapshot(snapshotFile);
if (StringUtils.isBlank(snapshotLocation) && snapshotAutoload) {
this.domain = this.initializeSnapshotFromAPI();
} else if (StringUtils.isNotBlank(snapshotLocation)) {
try {
this.domain = SnapshotLoader.loadSnapshot(snapshotLocation, environment);
Expand Down
Loading