Skip to content

Commit f1d3113

Browse files
authored
Merge pull request #612 from splitio/development
Development
2 parents d7f820b + c657460 commit f1d3113

File tree

22 files changed

+265
-38
lines changed

22 files changed

+265
-38
lines changed

CHANGES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
4.18.2 (Oct 15, 2025)
2+
- Fixed an issue where Manager.splitNames() return incorrect formatted result using redis storage and no custom prefix.
3+
- Added using String only parameter for treatments in FallbackTreatmentConfiguration class.
4+
15
4.18.1 (Sep 30, 2025)
26
- Fixed an issue where Streaming client hangs during token renew process.
37

client/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
<parent>
66
<groupId>io.split.client</groupId>
77
<artifactId>java-client-parent</artifactId>
8-
<version>4.18.1</version>
8+
<version>4.18.2</version>
99
</parent>
10-
<version>4.18.1</version>
10+
<version>4.18.2</version>
1111
<artifactId>java-client</artifactId>
1212
<packaging>jar</packaging>
1313
<name>Java Client</name>

client/src/main/java/io/split/client/dtos/FallbackTreatmentsConfiguration.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.split.client.dtos;
22

3+
import java.util.HashMap;
34
import java.util.Map;
45

56
public class FallbackTreatmentsConfiguration {
@@ -11,9 +12,54 @@ public FallbackTreatmentsConfiguration(FallbackTreatment globalFallbackTreatment
1112
_byFlagFallbackTreatment = byFlagFallbackTreatment;
1213
}
1314

15+
public FallbackTreatmentsConfiguration(Map<String, FallbackTreatment> byFlagFallbackTreatment) {
16+
_globalFallbackTreatment = null;
17+
_byFlagFallbackTreatment = byFlagFallbackTreatment;
18+
}
19+
20+
public FallbackTreatmentsConfiguration(HashMap<String, String> byFlagFallbackTreatment) {
21+
_globalFallbackTreatment = null;
22+
_byFlagFallbackTreatment = buildByFlagFallbackTreatment(byFlagFallbackTreatment);
23+
}
24+
25+
public FallbackTreatmentsConfiguration(FallbackTreatment globalFallbackTreatment) {
26+
_globalFallbackTreatment = globalFallbackTreatment;
27+
_byFlagFallbackTreatment = null;
28+
}
29+
30+
public FallbackTreatmentsConfiguration(String globalFallbackTreatment, Map<String, FallbackTreatment> byFlagFallbackTreatment) {
31+
_globalFallbackTreatment = new FallbackTreatment(globalFallbackTreatment);
32+
_byFlagFallbackTreatment = byFlagFallbackTreatment;
33+
}
34+
35+
public FallbackTreatmentsConfiguration(String globalFallbackTreatment) {
36+
_globalFallbackTreatment = new FallbackTreatment(globalFallbackTreatment);
37+
_byFlagFallbackTreatment = null;
38+
}
39+
40+
41+
public FallbackTreatmentsConfiguration(String globalFallbackTreatment, HashMap<String, String> byFlagFallbackTreatment) {
42+
_globalFallbackTreatment = new FallbackTreatment(globalFallbackTreatment);
43+
_byFlagFallbackTreatment = buildByFlagFallbackTreatment(byFlagFallbackTreatment);
44+
}
45+
46+
public FallbackTreatmentsConfiguration(FallbackTreatment globalFallbackTreatment, HashMap<String, String> byFlagFallbackTreatment) {
47+
_globalFallbackTreatment = globalFallbackTreatment;
48+
_byFlagFallbackTreatment = buildByFlagFallbackTreatment(byFlagFallbackTreatment);
49+
}
50+
1451
public FallbackTreatment getGlobalFallbackTreatment() {
1552
return _globalFallbackTreatment;
1653
}
1754

1855
public Map<String, FallbackTreatment> getByFlagFallbackTreatment() { return _byFlagFallbackTreatment;}
56+
57+
private Map<String, FallbackTreatment> buildByFlagFallbackTreatment(Map<String, String> byFlagFallbackTreatment) {
58+
Map<String, FallbackTreatment> result = new HashMap<>();
59+
for (Map.Entry<String, String> entry : byFlagFallbackTreatment.entrySet()) {
60+
result.put(entry.getKey(), new FallbackTreatment(entry.getValue()));
61+
}
62+
63+
return result;
64+
}
1965
}

client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public FetchResult forceRefresh(FetchOptions options) {
100100
Thread.currentThread().interrupt();
101101
return new FetchResult(false, true, new HashSet<>());
102102
} catch (Exception e) {
103-
_log.error("RefreshableSplitFetcher failed: " + e.getMessage());
103+
_log.error("SplitFetcherImp failed: " + e.getMessage());
104104
if (_log.isDebugEnabled()) {
105105
_log.debug("Reason:", e);
106106
}
@@ -166,4 +166,4 @@ private Set<String> runWithoutExceptionHandling(FetchOptions options) throws Int
166166

167167
return segments;
168168
}
169-
}
169+
}

client/src/test/java/io/split/client/JsonLocalhostSplitFactoryTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.split.client;
22

3+
import io.split.client.dtos.FallbackTreatment;
4+
import io.split.client.dtos.FallbackTreatmentsConfiguration;
35
import org.junit.Assert;
46
import org.junit.Test;
57

@@ -12,10 +14,14 @@ public class JsonLocalhostSplitFactoryTest {
1214

1315
@Test
1416
public void works() throws IOException, URISyntaxException, InterruptedException, TimeoutException {
17+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-global"),
18+
new HashMap<String, FallbackTreatment>() {{ put("feature", new FallbackTreatment("off-local", "{\"prop2\", \"val2\"}")); }});
19+
1520
SplitClientConfig config = SplitClientConfig.builder()
1621
.splitFile("src/test/resources/splits_localhost.json")
1722
.segmentDirectory("src/test/resources")
1823
.setBlockUntilReadyTimeout(10000)
24+
.fallbackTreatments(fallbackTreatmentsConfiguration)
1925
.build();
2026
SplitFactory splitFactory = SplitFactoryBuilder.build("localhost", config);
2127
SplitClient client = splitFactory.client();
@@ -30,6 +36,9 @@ public void works() throws IOException, URISyntaxException, InterruptedException
3036
Assert.assertEquals("off", client.getTreatment("bilal", "test_split"));
3137
Assert.assertEquals("on", client.getTreatment("bilal", "push_test"));
3238
Assert.assertEquals("on_whitelist", client.getTreatment("admin", "push_test"));
39+
Assert.assertEquals("off-local", client.getTreatment("bilal", "feature"));
40+
Assert.assertEquals("on-global", client.getTreatment("bilal", "feature2"));
41+
3342
client.destroy();
3443
}
3544

client/src/test/java/io/split/client/LocalhostSplitFactoryTest.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package io.split.client;
22

33
import com.google.common.collect.Maps;
4+
import io.split.client.dtos.FallbackTreatment;
5+
import io.split.client.dtos.FallbackTreatmentsConfiguration;
46
import io.split.client.utils.LocalhostUtils;
57
import io.split.grammar.Treatments;
8+
import org.junit.Assert;
69
import org.junit.Rule;
710
import org.junit.Test;
811
import org.junit.rules.TemporaryFolder;
912

1013
import java.io.File;
1114
import java.io.IOException;
1215
import java.net.URISyntaxException;
16+
import java.util.HashMap;
1317
import java.util.Map;
1418

1519
import static org.junit.Assert.assertEquals;
@@ -35,7 +39,9 @@ public void works() throws IOException, URISyntaxException, InterruptedException
3539

3640
LocalhostUtils.writeFile(file, map);
3741

38-
SplitClientConfig config = SplitClientConfig.builder().splitFile(folder.getRoot().getAbsolutePath()).build();
42+
SplitClientConfig config = SplitClientConfig.builder()
43+
.splitFile(folder.getRoot().getAbsolutePath())
44+
.build();
3945
SplitFactory splitFactory = SplitFactoryBuilder.build("localhost", config);
4046
SplitClient client = splitFactory.client();
4147

@@ -48,4 +54,30 @@ public void works() throws IOException, URISyntaxException, InterruptedException
4854
assertEquals("a", client.getTreatment("user1", "test"));
4955
assertEquals("a", client.getTreatment("user2", "test"));
5056
}
57+
58+
@Test
59+
public void testFallbackTreatments() throws IOException, URISyntaxException, InterruptedException {
60+
File file = folder.newFile(LegacyLocalhostSplitChangeFetcher.FILENAME);
61+
62+
Map<SplitAndKey, LocalhostSplit> map = Maps.newHashMap();
63+
map.put(SplitAndKey.of("onboarding"), LocalhostSplit.of("on"));
64+
map.put(SplitAndKey.of("onboarding", "user1"), LocalhostSplit.of("off"));
65+
map.put(SplitAndKey.of("onboarding", "user2"), LocalhostSplit.of("off"));
66+
map.put(SplitAndKey.of("test"), LocalhostSplit.of("a"));
67+
68+
LocalhostUtils.writeFile(file, map);
69+
70+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-global"),
71+
new HashMap<String, FallbackTreatment>() {{ put("feature", new FallbackTreatment("off-local", "{\"prop2\", \"val2\"}")); }});
72+
73+
SplitClientConfig config = SplitClientConfig.builder()
74+
.splitFile(folder.getRoot().getAbsolutePath())
75+
.fallbackTreatments(fallbackTreatmentsConfiguration)
76+
.build();
77+
SplitFactory splitFactory = SplitFactoryBuilder.build("localhost", config);
78+
SplitClient client = splitFactory.client();
79+
80+
assertEquals("off-local", client.getTreatment("user1", "feature"));
81+
assertEquals("on-global", client.getTreatment("user1", "feature2"));
82+
}
5183
}

client/src/test/java/io/split/client/LocalhostSplitFactoryYamlTest.java

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.split.client;
22

3+
import io.split.client.dtos.FallbackTreatment;
4+
import io.split.client.dtos.FallbackTreatmentsConfiguration;
35
import io.split.client.utils.LocalhostUtils;
46
import io.split.grammar.Treatments;
57
import org.junit.Rule;
@@ -11,10 +13,7 @@
1113
import java.io.IOException;
1214
import java.io.StringWriter;
1315
import java.net.URISyntaxException;
14-
import java.util.ArrayList;
15-
import java.util.LinkedHashMap;
16-
import java.util.List;
17-
import java.util.Map;
16+
import java.util.*;
1817

1918
import static org.hamcrest.MatcherAssert.assertThat;
2019
import static org.hamcrest.Matchers.is;
@@ -106,4 +105,59 @@ public void works() throws IOException, URISyntaxException {
106105
// unchanged
107106
assertThat(client.getTreatment("user_b", "split_1"), is(equalTo("on")));
108107
}
108+
109+
@Test
110+
public void testFallbackTreatment() throws IOException, URISyntaxException {
111+
File file = folder.newFile(SplitClientConfig.LOCALHOST_DEFAULT_FILE);
112+
113+
List<Map<String, Object>> allSplits = new ArrayList();
114+
115+
Map<String, Object> split1_user_a = new LinkedHashMap<>();
116+
Map<String, Object> split1_user_a_data = new LinkedHashMap<>();
117+
split1_user_a_data.put("keys", "user_a");
118+
split1_user_a_data.put("treatment", "off");
119+
split1_user_a_data.put("config", "{ \"size\" : 20 }");
120+
split1_user_a.put("split_1", split1_user_a_data);
121+
allSplits.add(split1_user_a);
122+
123+
Map<String, Object> split1_user_b = new LinkedHashMap<>();
124+
Map<String, Object> split1_user_b_data = new LinkedHashMap<>();
125+
split1_user_b_data.put("keys", "user_b");
126+
split1_user_b_data.put("treatment", "on");
127+
split1_user_b.put("split_1", split1_user_b_data);
128+
allSplits.add(split1_user_b);
129+
130+
Map<String, Object> split2_user_a = new LinkedHashMap<>();
131+
Map<String, Object> split2_user_a_data = new LinkedHashMap<>();
132+
split2_user_a_data.put("keys", "user_a");
133+
split2_user_a_data.put("treatment", "off");
134+
split2_user_a_data.put("config", "{ \"size\" : 20 }");
135+
split2_user_a.put("split_2", split2_user_a_data);
136+
allSplits.add(split2_user_a);
137+
138+
139+
Yaml yaml = new Yaml();
140+
StringWriter writer = new StringWriter();
141+
yaml.dump(allSplits, writer);
142+
143+
String expectedYaml = "- split_1: {keys: user_a, treatment: 'off', config: '{ \"size\" : 20 }'}\n" +
144+
"- split_1: {keys: user_b, treatment: 'on'}\n" +
145+
"- split_2: {keys: user_a, treatment: 'off', config: '{ \"size\" : 20 }'}\n";
146+
147+
assertEquals(expectedYaml, writer.toString());
148+
149+
LocalhostUtils.writeFile(file, writer);
150+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-global"),
151+
new HashMap<String, FallbackTreatment>() {{ put("feature", new FallbackTreatment("off-local", "{\"prop2\", \"val2\"}")); }});
152+
153+
SplitClientConfig config = SplitClientConfig.builder()
154+
.splitFile(file.getAbsolutePath())
155+
.fallbackTreatments(fallbackTreatmentsConfiguration)
156+
.build();
157+
SplitFactory splitFactory = SplitFactoryBuilder.build("localhost", config);
158+
SplitClient client = splitFactory.client();
159+
160+
assertEquals("off-local", client.getTreatment("user1", "feature"));
161+
assertEquals("on-global", client.getTreatment("user1", "feature2"));
162+
}
109163
}

client/src/test/java/io/split/client/SplitClientConfigTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,18 +367,18 @@ public void mustUseP12PassKeyWithProxyMtls() throws MalformedURLException, FileN
367367
@Test
368368
public void fallbackTreatmentCheckRegex() {
369369
SplitClientConfig config = SplitClientConfig.builder()
370-
.fallbackTreatments(new FallbackTreatmentsConfiguration(new FallbackTreatment("12#2"), null))
370+
.fallbackTreatments(new FallbackTreatmentsConfiguration(new FallbackTreatment("12#2")))
371371
.build();
372372
Assert.assertEquals(null, config.fallbackTreatments().getGlobalFallbackTreatment().getTreatment());
373373

374374
config = SplitClientConfig.builder()
375-
.fallbackTreatments(new FallbackTreatmentsConfiguration(null, new HashMap<String, FallbackTreatment>() {{ put("flag", new FallbackTreatment("12#2")); }} ))
375+
.fallbackTreatments(new FallbackTreatmentsConfiguration(new HashMap<String, FallbackTreatment>() {{ put("flag", new FallbackTreatment("12#2")); }} ))
376376
.build();
377377
Assert.assertEquals(0, config.fallbackTreatments().getByFlagFallbackTreatment().size());
378378

379379
config = SplitClientConfig.builder()
380380
.fallbackTreatments(new FallbackTreatmentsConfiguration(
381-
new FallbackTreatment("on"),
381+
"on",
382382
new HashMap<String, FallbackTreatment>() {{ put("flag", new FallbackTreatment("off")); }} ))
383383
.build();
384384
Assert.assertEquals("on", config.fallbackTreatments().getGlobalFallbackTreatment().getTreatment());

client/src/test/java/io/split/client/SplitClientImplTest.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,8 +2308,7 @@ public void fallbackTreatmentWithExceptionsResult() {
23082308

23092309
String fallbcakConfigGlobal = "{\"prop1\", \"val1\"}";
23102310
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(
2311-
new FallbackTreatment("on", fallbcakConfigGlobal),
2312-
null);
2311+
new FallbackTreatment("on", fallbcakConfigGlobal));
23132312
FallbackTreatmentCalculator fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration);
23142313

23152314
SplitClientImpl client = new SplitClientImpl(
@@ -2388,7 +2387,7 @@ public void fallbackTreatmentWithExceptionsResult() {
23882387
assertEquals("off", client.getTreatmentsWithConfigByFlagSets("[email protected]", Arrays.asList("flag")).get("feature").treatment());
23892388
assertEquals(fallbcakConfigByFlag, client.getTreatmentsWithConfigByFlagSets("[email protected]", Arrays.asList("flag")).get("feature").config());
23902389

2391-
fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null,
2390+
fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(
23922391
new HashMap<String, FallbackTreatment>() {{ put("feature", new FallbackTreatment("off", fallbcakConfigByFlag)); }});
23932392

23942393
fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration);
@@ -2458,8 +2457,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() {
24582457

24592458
String fallbcakConfigGlobal = "{\"prop1\", \"val1\"}";
24602459
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(
2461-
new FallbackTreatment("on", fallbcakConfigGlobal),
2462-
null);
2460+
new FallbackTreatment("on", fallbcakConfigGlobal));
24632461
FallbackTreatmentCalculator fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration);
24642462

24652463
SplitClientImpl client = new SplitClientImpl(
@@ -2573,7 +2571,7 @@ public void fallbackTreatmentWithSplitNotFoundResult() {
25732571
assertEquals("on", results.get("test3").treatment());
25742572
assertEquals(fallbcakConfigGlobal, results.get("test3").config());
25752573

2576-
fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null,
2574+
fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(
25772575
new HashMap<String, FallbackTreatment>() {{ put("test2", new FallbackTreatment("off-fallback", fallbcakConfigByFlag)); }});
25782576

25792577
fallbackTreatmentCalculator = new FallbackTreatmentCalculatorImp(fallbackTreatmentsConfiguration);

client/src/test/java/io/split/client/SplitClientIntegrationTest.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,8 +1282,7 @@ public MockResponse dispatch(RecordedRequest request) {
12821282

12831283
server.start();
12841284
String serverURL = String.format("http://%s:%s", server.getHostName(), server.getPort());
1285-
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-fallback", "{\"prop1\", \"val1\"}"),
1286-
null);
1285+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-fallback", "{\"prop1\", \"val1\"}"));
12871286

12881287
SplitClientConfig config = SplitClientConfig.builder()
12891288
.setBlockUntilReadyTimeout(10000)
@@ -1354,7 +1353,7 @@ public MockResponse dispatch(RecordedRequest request) {
13541353

13551354
server.start();
13561355
String serverURL = String.format("http://%s:%s", server.getHostName(), server.getPort());
1357-
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(null,
1356+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(
13581357
new HashMap<String, FallbackTreatment>() {{ put("feature", new FallbackTreatment("off-fallback", "{\"prop2\", \"val2\"}")); }});
13591358

13601359
SplitClientConfig config = SplitClientConfig.builder()
@@ -1427,8 +1426,7 @@ public MockResponse dispatch(RecordedRequest request) throws InterruptedExceptio
14271426

14281427
server.start();
14291428
String serverURL = String.format("http://%s:%s", server.getHostName(), server.getPort());
1430-
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration(new FallbackTreatment("on-fallback", "{\"prop1\", \"val1\"}"),
1431-
null);
1429+
FallbackTreatmentsConfiguration fallbackTreatmentsConfiguration = new FallbackTreatmentsConfiguration("on-fallback");
14321430

14331431
SplitClientConfig config = SplitClientConfig.builder()
14341432
.setBlockUntilReadyTimeout(10000)

0 commit comments

Comments
 (0)