Skip to content

Commit b284848

Browse files
authored
Closes #368 - allow diff Switcher Key constant name (#369)
1 parent 150f22f commit b284848

15 files changed

+123
-24
lines changed

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Instead of using SwitcherContext, which is used to automatically load from the s
9494

9595
```java
9696
MyAppFeatures.configure(ContextBuilder.builder()
97-
.contextLocation("com.switcherapi.playground.Features")
97+
.context(Features.class.getName())
9898
.apiKey("API_KEY")
9999
.url("https://switcher-api.com")
100100
.domain("Playground")
@@ -130,8 +130,15 @@ class MySwitcherClientConfig extends SwitcherContextBase {
130130

131131
### Defining your features
132132

133-
Create a class that extends SwitcherContext if you are loading the configuration from the switcherapi.properties file.
134-
Or use SwitcherContextBase to define the configuration using the ContextBuilder or SwitcherConfig.
133+
Create a class that extends `SwitcherContext` if you are loading the configuration from the switcherapi.properties file.<br>
134+
Or use `SwitcherContextBase` to define the configuration using the ContextBuilder or SwitcherConfig.
135+
136+
Switcher Keys are defined using the @SwitcherKey annotation and must be public static final String.<br>
137+
- Public because you will need to access it from other places of your code.
138+
- Static because you will access it without instantiating the class.
139+
- Final because the value must not be changed during runtime.
140+
141+
The attribute name can be defined as you want (e.g. FEATURE01, FEATURE_01, myFeatureOne, etc), but the value must be the exact Switcher Key defined in Switcher Management or snapshot files.
135142

136143
```java
137144
public class MyAppFeatures extends SwitcherContext {

src/main/java/com/switcherapi/client/SwitcherContextBase.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
* // Initialize the Switcher Client using ContextBuilder
6666
* public void configureClient() {
6767
* Features.configure(ContextBuilder.builder()
68-
* .context("com.business.config.Features")
68+
* .context(Features.class.getName())
6969
* .apiKey("API_KEY")
7070
* .domain("Playground")
7171
* .component("switcher-playground")
@@ -243,12 +243,22 @@ private static void registerSwitcherKeys() {
243243
* @param fields to be registered
244244
*/
245245
private static void registerSwitcherKey(Field[] fields) {
246-
switcherKeys = Optional.ofNullable(switcherKeys).orElse(new HashSet<>());
246+
Set<String> switcherKeys = new HashSet<>();
247+
247248
for (Field field : fields) {
248249
if (field.isAnnotationPresent(SwitcherKey.class)) {
249-
switcherKeys.add(field.getName());
250+
try {
251+
switcherKeys.add(field.get(null).toString());
252+
} catch (Exception e) {
253+
throw new SwitcherContextException(
254+
String.format("Error retrieving Switcher Key value from field %s", field.getName()));
255+
}
250256
}
251257
}
258+
259+
if (!switcherKeys.isEmpty()) {
260+
setSwitcherKeys(switcherKeys);
261+
}
252262
}
253263

254264
/**
@@ -538,8 +548,13 @@ private static synchronized void setContextBase(SwitcherContextBase contextBase)
538548
SwitcherContextBase.contextBase = contextBase;
539549
}
540550

541-
private static synchronized void setSwitcherKeys(Set<String> switcherKeys) {
551+
private static synchronized void setSwitcherKeys(Set<String> switcherKeys)
552+
throws SwitcherContextException {
542553
SwitcherContextBase.switcherKeys = switcherKeys;
554+
555+
if (switcherKeys.stream().anyMatch(StringUtils::isBlank)) {
556+
throw new SwitcherContextException("One or more Switcher Keys are empty");
557+
}
543558
}
544559

545560
}

src/test/java/com/switcherapi/Switchers.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,8 @@ public class Switchers extends SwitcherContext {
142142

143143
@SwitcherKey
144144
public static final String NOT_FOUND_KEY = "NOT_FOUND_KEY";
145+
146+
@SwitcherKey
147+
public static final String friendlyFeatureName = "USECASE1";
148+
145149
}

src/test/java/com/switcherapi/client/SwitcherContextBuilderTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class SwitcherContextBuilderTest {
2121
void shouldReturnSuccess() {
2222
//given
2323
configure(ContextBuilder.builder(true)
24-
.context(SwitchersBase.class.getCanonicalName())
24+
.context(SwitchersBase.class.getName())
2525
.url("http://localhost:3000")
2626
.apiKey("API_KEY")
2727
.domain("switcher-domain")
@@ -41,7 +41,7 @@ void shouldReturnSuccess() {
4141
void shouldReturnError_snapshotNotLoaded() {
4242
//given
4343
configure(ContextBuilder.builder(true)
44-
.context(SwitchersBase.class.getCanonicalName())
44+
.context(SwitchersBase.class.getName())
4545
.url("http://localhost:3000")
4646
.apiKey("API_KEY")
4747
.domain("switcher-domain")
@@ -59,7 +59,7 @@ void shouldReturnError_snapshotNotLoaded() {
5959
void shouldThrowError_wrongContextKeyTypeUsage() {
6060
//given
6161
configure(ContextBuilder.builder(true)
62-
.context(SwitchersBase.class.getCanonicalName())
62+
.context(SwitchersBase.class.getName())
6363
.domain("switcher-domain")
6464
.snapshotLocation(SNAPSHOTS_LOCAL)
6565
.local(true));

src/test/java/com/switcherapi/client/SwitcherContextRemoteExecutorTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void shouldConfigureRemotePoolSize() {
3636

3737
//given
3838
SwitchersBase.configure(ContextBuilder.builder(true)
39-
.context(SwitchersBase.class.getCanonicalName())
39+
.context(SwitchersBase.class.getName())
4040
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
4141
.apiKey("API_KEY")
4242
.domain("switcher-domain")
@@ -67,7 +67,7 @@ void shouldConfigureRemoteTimeout() {
6767

6868
//given
6969
SwitchersBase.configure(ContextBuilder.builder(true)
70-
.context(SwitchersBase.class.getCanonicalName())
70+
.context(SwitchersBase.class.getName())
7171
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
7272
.apiKey("API_KEY")
7373
.domain("switcher-domain")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.switcherapi.client;
2+
3+
import com.switcherapi.client.exception.SwitcherContextException;
4+
import org.apache.commons.lang3.StringUtils;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.nio.file.Paths;
8+
9+
import static org.junit.jupiter.api.Assertions.assertEquals;
10+
import static org.junit.jupiter.api.Assertions.assertThrows;
11+
12+
class SwitcherFail3Test {
13+
14+
private static final String SNAPSHOTS_LOCAL = Paths.get(StringUtils.EMPTY).toAbsolutePath() + "/src/test/resources";
15+
16+
@Test
17+
void shouldNotRegisterSwitcher_nullKey() {
18+
//given
19+
TestCaseNull.configure(ContextBuilder.builder()
20+
.context(TestCaseNull.class.getName())
21+
.snapshotLocation(SNAPSHOTS_LOCAL)
22+
.local(true));
23+
24+
//test
25+
Exception exception = assertThrows(SwitcherContextException.class, TestCaseNull::initializeClient);
26+
assertEquals("Something went wrong: Context has errors - Error retrieving Switcher Key value from field NULL_KEY",
27+
exception.getMessage());
28+
}
29+
30+
@Test
31+
void shouldNotRegisterSwitcher_emptyKey() {
32+
//given
33+
TestCaseEmpty.configure(ContextBuilder.builder()
34+
.context(TestCaseEmpty.class.getName())
35+
.snapshotLocation(SNAPSHOTS_LOCAL)
36+
.local(true));
37+
38+
//test
39+
Exception exception = assertThrows(SwitcherContextException.class, TestCaseEmpty::initializeClient);
40+
assertEquals("Something went wrong: Context has errors - One or more Switcher Keys are empty",
41+
exception.getMessage());
42+
}
43+
44+
static class TestCaseNull extends SwitcherContextBase {
45+
@SwitcherKey
46+
public static final String NULL_KEY = null;
47+
}
48+
49+
static class TestCaseEmpty extends SwitcherContextBase {
50+
@SwitcherKey
51+
public static final String EMPTY_KEY = "";
52+
}
53+
54+
}

src/test/java/com/switcherapi/client/SwitcherLocal1Test.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ void localShouldReturnTrue() {
5757
// check result history
5858
assertTrue(switcher.getLastExecutionResult().isItOn());
5959
}
60+
61+
@Test
62+
void localShouldReturnTrueUsingFriendlyConstantName() {
63+
SwitcherRequest switcher = Switchers.getSwitcher(Switchers.friendlyFeatureName, true);
64+
65+
assertNull(switcher.getLastExecutionResult());
66+
assertTrue(switcher.isItOn());
67+
68+
// check result history
69+
assertTrue(switcher.getLastExecutionResult().isItOn());
70+
}
6071

6172
@Test
6273
void localShouldReturnFalse() {

src/test/java/com/switcherapi/client/SwitcherSnapshotAutoUpdateTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void shouldUpdateSnapshot_local() {
8585

8686
//that
8787
Switchers.configure(ContextBuilder.builder(true)
88-
.context(Switchers.class.getCanonicalName())
88+
.context(Switchers.class.getName())
8989
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
9090
.apiKey("[API_KEY]")
9191
.snapshotLocation(SNAPSHOTS_LOCAL)
@@ -110,7 +110,7 @@ void shouldUpdateSnapshot_remote() {
110110

111111
//that
112112
Switchers.configure(ContextBuilder.builder(true)
113-
.context(Switchers.class.getCanonicalName())
113+
.context(Switchers.class.getName())
114114
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
115115
.apiKey("[API_KEY]")
116116
.domain("Test")
@@ -137,7 +137,7 @@ void shouldNotUpdateSnapshot_whenNoUpdateAvailable() {
137137

138138
//that
139139
Switchers.configure(ContextBuilder.builder(true)
140-
.context(Switchers.class.getCanonicalName())
140+
.context(Switchers.class.getName())
141141
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
142142
.apiKey("[API_KEY]")
143143
.snapshotLocation(SNAPSHOTS_LOCAL)
@@ -165,7 +165,7 @@ void shouldUpdateSnapshot_remote_inMemory() {
165165

166166
//that
167167
Switchers.configure(ContextBuilder.builder(true)
168-
.context(Switchers.class.getCanonicalName())
168+
.context(Switchers.class.getName())
169169
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
170170
.apiKey("[API_KEY]")
171171
.environment("generated_mock_default_5")
@@ -192,7 +192,7 @@ void shouldNotKillThread_whenAPI_wentLocal() {
192192

193193
//that
194194
Switchers.configure(ContextBuilder.builder(true)
195-
.context(Switchers.class.getCanonicalName())
195+
.context(Switchers.class.getName())
196196
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
197197
.apiKey("[API_KEY]")
198198
.environment("generated_mock_default_6")
@@ -227,7 +227,7 @@ void shouldRestartSnapshotAutoUpdate_whenAlreadySetup() {
227227

228228
//that
229229
Switchers.configure(ContextBuilder.builder(true)
230-
.context(Switchers.class.getCanonicalName())
230+
.context(Switchers.class.getName())
231231
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
232232
.apiKey("[API_KEY]")
233233
.environment("generated_mock_default_6")

src/test/java/com/switcherapi/client/service/local/SwitcherLocalServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class SwitcherLocalServiceTest {
3737
static void init() {
3838
executorService = Executors.newSingleThreadExecutor();
3939
SwitchersBase.configure(ContextBuilder.builder()
40-
.context("com.switcherapi.SwitchersBase")
40+
.context(SwitchersBase.class.getName())
4141
.snapshotLocation(SNAPSHOTS_LOCAL)
4242
.environment("default")
4343
.local(true));

src/test/java/com/switcherapi/client/utils/SnapshotWatcherContextTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static void setupContext() throws IOException {
1919
generateFixture();
2020

2121
SwitchersBase.configure(ContextBuilder.builder(true)
22-
.context(SwitchersBase.class.getCanonicalName())
22+
.context(SwitchersBase.class.getName())
2323
.environment("generated_watcher_default")
2424
.snapshotLocation(SNAPSHOTS_LOCAL)
2525
.snapshotWatcher(true)

0 commit comments

Comments
 (0)