Skip to content

Commit b3278d3

Browse files
authored
Merge pull request #54 from SentryMan/real-cache
cache interpolation results
2 parents 2676363 + 3232042 commit b3278d3

File tree

7 files changed

+35
-28
lines changed

7 files changed

+35
-28
lines changed

validator/src/main/java/io/avaje/validation/adapter/ValidationContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ interface Message {
3737
String template();
3838

3939
Map<String, Object> attributes();
40+
41+
String lookupkey();
4042
}
4143

4244
/**

validator/src/main/java/io/avaje/validation/core/DMessage.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,20 @@
44

55
import java.util.Map;
66

7-
final class DMessage implements ValidationContext.Message {
7+
final record DMessage(String template, Map<String, Object> attributes, int dedupNumber)
8+
implements ValidationContext.Message {
89

9-
private final String template;
10-
private final Map<String, Object> attributes;
10+
// templates can be the same across multiple adapters
11+
// these numbers ensures no cache collision
12+
private static int messageCounter = 0;
1113

1214
DMessage(String template, Map<String, Object> attributes) {
13-
this.template = template;
14-
this.attributes = attributes;
15-
}
1615

17-
@Override
18-
public String template() {
19-
return template;
16+
this(template, attributes, messageCounter++);
2017
}
2118

2219
@Override
23-
public Map<String, Object> attributes() {
24-
return attributes;
20+
public String lookupkey() {
21+
return template + dedupNumber;
2522
}
2623
}

validator/src/main/java/io/avaje/validation/core/DTemplateLookup.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package io.avaje.validation.core;
22

3-
import java.util.HashMap;
43
import java.util.Locale;
5-
import java.util.Map;
64

75
final class DTemplateLookup {
86
private final DResourceBundleManager bundleManager;
9-
private final Map<String, String> messageCache = new HashMap<>();
107

118
DTemplateLookup(DResourceBundleManager defaultBundle) {
129
this.bundleManager = defaultBundle;
@@ -17,7 +14,7 @@ String lookup(String template, Locale resolvedLocale) {
1714
return template;
1815
}
1916
final String key = template.substring(1, template.length() - 1);
20-
final String msg = messageCache.computeIfAbsent(key + resolvedLocale, k -> bundleManager.message(key, resolvedLocale));
17+
final String msg = bundleManager.message(key, resolvedLocale);
2118
if (msg != null) {
2219
return msg;
2320
}

validator/src/main/java/io/avaje/validation/core/DValidationType.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package io.avaje.validation.core;
22

3-
import io.avaje.validation.adapter.ValidationAdapter;
4-
import io.avaje.validation.adapter.ValidationRequest;
5-
6-
import java.lang.reflect.Type;
73
import java.util.Locale;
84

5+
import io.avaje.validation.adapter.ValidationAdapter;
6+
97
final class DValidationType<T> implements ValidationType<T> {
108

119
private final DValidator validator;

validator/src/main/java/io/avaje/validation/core/DValidator.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.lang.reflect.Type;
1010
import java.util.ArrayList;
1111
import java.util.Collections;
12+
import java.util.HashMap;
1213
import java.util.List;
1314
import java.util.Locale;
1415
import java.util.Map;
@@ -18,7 +19,6 @@
1819

1920
import io.avaje.lang.Nullable;
2021
import io.avaje.validation.Validator;
21-
import io.avaje.validation.Validator.AnnotationAdapterBuilder;
2222
import io.avaje.validation.adapter.ValidationAdapter;
2323
import io.avaje.validation.adapter.ValidationContext;
2424
import io.avaje.validation.adapter.ValidationRequest;
@@ -32,6 +32,7 @@ final class DValidator implements Validator, ValidationContext {
3232
private final MessageInterpolator interpolator;
3333
private final LocaleResolver localeResolver;
3434
private final DTemplateLookup templateLookup;
35+
private final Map<String, String> messageCache = new ConcurrentHashMap<>();
3536

3637
DValidator(
3738
List<AdapterFactory> factories,
@@ -118,9 +119,14 @@ ValidationRequest request(@Nullable Locale locale) {
118119
String interpolate(Message msg, Locale requestLocale) {
119120
// resolve the locale to use to produce the message
120121
final Locale locale = localeResolver.resolve(requestLocale);
121-
// lookup in resource bundles using resolved locale and template
122-
final String template = templateLookup.lookup(msg.template(), locale);
123-
return interpolator.interpolate(template, msg.attributes());
122+
123+
return messageCache.computeIfAbsent(
124+
msg.lookupkey() + locale,
125+
k -> {
126+
// lookup in resource bundles using resolved locale and template
127+
final String template = templateLookup.lookup(msg.template(), locale);
128+
return interpolator.interpolate(template, msg.attributes());
129+
});
124130
}
125131

126132
/** Implementation of Validator.Builder. */

validator/src/test/java/io/avaje/validation/core/BasicTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
abstract class BasicTest {
1313

14-
protected final Validator validator =
14+
protected static final Validator validator =
1515
Validator.builder()
1616
.add(Address.class, AddressValidationAdapter::new)
1717
.add(Contact.class, ContactValidationAdapter::new)

validator/src/test/java/io/avaje/validation/core/NotNullLocaleTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,22 @@ class NotNullLocaleTest extends BasicTest {
1111

1212
@Test
1313
void testSize_DefaultLocale() {
14-
var contact = new Contact("ok", null);
15-
ConstraintViolation constraint = one(contact, Locale.ENGLISH);
14+
final var contact = new Contact("ok", null);
15+
final ConstraintViolation constraint = one(contact, Locale.ENGLISH);
16+
assertThat(constraint.message()).isEqualTo("must not be null");
17+
}
18+
19+
@Test
20+
void testSize_DefaultLocale2() {
21+
final var contact = new Contact("ok", null);
22+
final ConstraintViolation constraint = one(contact, Locale.ENGLISH);
1623
assertThat(constraint.message()).isEqualTo("must not be null");
1724
}
1825

1926
@Test
2027
void testSize_DE() {
21-
var contact = new Contact("ok", null);
22-
ConstraintViolation constraint = one(contact, Locale.GERMAN);
28+
final var contact = new Contact("ok", null);
29+
final ConstraintViolation constraint = one(contact, Locale.GERMAN);
2330
assertThat(constraint.message()).isEqualTo("darf nicht null sein");
2431
}
2532

0 commit comments

Comments
 (0)