17
17
package org .springframework .data .gemfire .config .annotation ;
18
18
19
19
import static org .springframework .data .gemfire .config .annotation .EnableEviction .EvictionPolicy ;
20
- import static org .springframework .data .gemfire .util .ArrayUtils .nullSafeArray ;
21
- import static org .springframework .data .gemfire .util .CollectionUtils .nullSafeIterable ;
22
- import static org .springframework .data .gemfire .util .RuntimeExceptionFactory .newIllegalArgumentException ;
23
20
import static org .springframework .data .gemfire .util .RuntimeExceptionFactory .newIllegalStateException ;
24
21
25
22
import java .lang .annotation .Annotation ;
30
27
import java .util .Set ;
31
28
import java .util .function .Supplier ;
32
29
30
+ import org .apache .geode .cache .AttributesMutator ;
33
31
import org .apache .geode .cache .EvictionAttributes ;
34
32
import org .apache .geode .cache .Region ;
33
+ import org .apache .geode .cache .RegionAttributes ;
35
34
import org .apache .geode .cache .util .ObjectSizer ;
36
35
37
36
import org .springframework .beans .BeansException ;
41
40
import org .springframework .context .annotation .Bean ;
42
41
import org .springframework .context .annotation .Configuration ;
43
42
import org .springframework .context .annotation .ImportAware ;
43
+ import org .springframework .context .event .ContextRefreshedEvent ;
44
+ import org .springframework .context .event .EventListener ;
44
45
import org .springframework .core .annotation .AnnotationAttributes ;
45
46
import org .springframework .core .type .AnnotationMetadata ;
46
47
import org .springframework .data .gemfire .PeerRegionFactoryBean ;
51
52
import org .springframework .data .gemfire .eviction .EvictionActionType ;
52
53
import org .springframework .data .gemfire .eviction .EvictionAttributesFactoryBean ;
53
54
import org .springframework .data .gemfire .eviction .EvictionPolicyType ;
55
+ import org .springframework .data .gemfire .util .ArrayUtils ;
56
+ import org .springframework .data .gemfire .util .CollectionUtils ;
54
57
import org .springframework .lang .NonNull ;
58
+ import org .springframework .lang .Nullable ;
55
59
import org .springframework .util .Assert ;
56
60
import org .springframework .util .StringUtils ;
57
61
60
64
* Eviction policy configuration on cache {@link Region Regions}.
61
65
*
62
66
* @author John Blum
67
+ * @see org.apache.geode.cache.EvictionAttributes
68
+ * @see org.apache.geode.cache.Region
69
+ * @see org.apache.geode.cache.util.ObjectSizer
63
70
* @see org.springframework.beans.factory.config.BeanPostProcessor
64
71
* @see org.springframework.context.ApplicationContext
65
72
* @see org.springframework.context.ApplicationContextAware
66
73
* @see org.springframework.context.annotation.Bean
67
74
* @see org.springframework.context.annotation.Configuration
68
75
* @see org.springframework.context.annotation.ImportAware
69
- * @see PeerRegionFactoryBean
76
+ * @see org.springframework.data.gemfire. PeerRegionFactoryBean
70
77
* @see org.springframework.data.gemfire.ResolvableRegionFactoryBean
71
78
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
72
79
* @see org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport
73
80
* @see org.springframework.data.gemfire.eviction.EvictionActionType
74
81
* @see org.springframework.data.gemfire.eviction.EvictionAttributesFactoryBean
75
82
* @see org.springframework.data.gemfire.eviction.EvictionPolicyType
76
- * @see org.apache.geode.cache.EvictionAttributes
77
- * @see org.apache.geode.cache.Region
78
- * @see org.apache.geode.cache.util.ObjectSizer
79
83
* @since 1.9.0
80
84
*/
81
85
@ Configuration
@@ -94,7 +98,7 @@ public class EvictionConfiguration extends AbstractAnnotationConfigSupport
94
98
* @see java.lang.Class
95
99
*/
96
100
@ Override
97
- protected Class <? extends Annotation > getAnnotationType () {
101
+ protected @ NonNull Class <? extends Annotation > getAnnotationType () {
98
102
return EnableEviction .class ;
99
103
}
100
104
@@ -115,15 +119,17 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
115
119
* @inheritDoc
116
120
*/
117
121
@ Override
118
- public void setImportMetadata (AnnotationMetadata importMetadata ) {
122
+ public void setImportMetadata (@ NonNull AnnotationMetadata importMetadata ) {
119
123
120
124
if (isAnnotationPresent (importMetadata )) {
121
125
122
126
AnnotationAttributes enableEvictionAttributes = getAnnotationAttributes (importMetadata );
123
127
124
128
AnnotationAttributes [] policies = enableEvictionAttributes .getAnnotationArray ("policies" );
125
129
126
- for (AnnotationAttributes evictionPolicyAttributes : nullSafeArray (policies , AnnotationAttributes .class )) {
130
+ for (AnnotationAttributes evictionPolicyAttributes :
131
+ ArrayUtils .nullSafeArray (policies , AnnotationAttributes .class )) {
132
+
127
133
this .evictionPolicyConfigurer =
128
134
ComposableEvictionPolicyConfigurer .compose (this .evictionPolicyConfigurer ,
129
135
EvictionPolicyMetaData .from (evictionPolicyAttributes , this .applicationContext ));
@@ -173,23 +179,47 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
173
179
};
174
180
}
175
181
182
+ @ SuppressWarnings ("unused" )
183
+ @ EventListener (ContextRefreshedEvent .class )
184
+ public void evictionContextRefreshedListener (@ NonNull ContextRefreshedEvent event ) {
185
+
186
+ ApplicationContext applicationContext = event .getApplicationContext ();
187
+
188
+ for (Region <?, ?> region : applicationContext .getBeansOfType (Region .class ).values ()) {
189
+ getEvictionPolicyConfigurer ().configure (region );
190
+ }
191
+ }
192
+
176
193
/**
177
- * {@link EvictionPolicyConfigurer} configures the Eviction policy of a GemFire {@link Region}.
194
+ * {@link EvictionPolicyConfigurer} configures the Eviction policy of an Apache Geode {@link Region}.
195
+ *
196
+ * @see java.lang.FunctionalInterface
178
197
*/
198
+ @ FunctionalInterface
179
199
protected interface EvictionPolicyConfigurer {
180
200
181
201
/**
182
- * Configure the Eviction policy on the given SDG {@link PeerRegionFactoryBean} or {@link ClientRegionFactoryBean}
183
- * used to create a GemFire {@link Region}.
202
+ * Configure the Eviction policy on the given SDG {@link ClientRegionFactoryBean}
203
+ * or {@link PeerRegionFactoryBean} used to create an Apache Geode {@link Region}.
184
204
*
185
- * @param regionFactoryBean {@link PeerRegionFactoryBean } or {@link ClientRegionFactoryBean } used to create
186
- * a GemFire {@link Region}.
205
+ * @param regionBean {@link ClientRegionFactoryBean } or {@link PeerRegionFactoryBean } used to create
206
+ * an Apache Geode {@link Region}.
187
207
* @return the given {@code regionFactoryBean}.
188
- * @see PeerRegionFactoryBean
208
+ * @see org.springframework.data.gemfire. PeerRegionFactoryBean
189
209
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
190
210
*/
191
- Object configure (Object regionFactoryBean );
211
+ Object configure (Object regionBean );
192
212
213
+ /**
214
+ * Configures the Eviction policy of the given Apache Geode {@link Region}.
215
+ *
216
+ * @param region {@link Region} on which to configure the Eviction policy.
217
+ * @return the given {@link Region}.
218
+ * @see org.apache.geode.cache.Region
219
+ */
220
+ default Region <?, ?> configure (Region <?, ?> region ) {
221
+ return region ;
222
+ }
193
223
}
194
224
195
225
/**
@@ -201,9 +231,6 @@ protected interface EvictionPolicyConfigurer {
201
231
*/
202
232
protected static class ComposableEvictionPolicyConfigurer implements EvictionPolicyConfigurer {
203
233
204
- private final EvictionPolicyConfigurer one ;
205
- private final EvictionPolicyConfigurer two ;
206
-
207
234
/**
208
235
* Composes the array of {@link EvictionPolicyConfigurer} objects into a single
209
236
* {@link EvictionPolicyConfigurer} implementation using the Composite Software Design Pattern.
@@ -215,8 +242,8 @@ protected static class ComposableEvictionPolicyConfigurer implements EvictionPol
215
242
* @see #compose(Iterable)
216
243
*/
217
244
@ SuppressWarnings ("unused" )
218
- protected static EvictionPolicyConfigurer compose (EvictionPolicyConfigurer [] array ) {
219
- return compose (Arrays .asList (nullSafeArray (array , EvictionPolicyConfigurer .class )));
245
+ protected static @ Nullable EvictionPolicyConfigurer compose (EvictionPolicyConfigurer [] array ) {
246
+ return compose (Arrays .asList (ArrayUtils . nullSafeArray (array , EvictionPolicyConfigurer .class )));
220
247
}
221
248
222
249
/**
@@ -229,11 +256,11 @@ protected static EvictionPolicyConfigurer compose(EvictionPolicyConfigurer[] arr
229
256
* @see org.springframework.data.gemfire.config.annotation.EvictionConfiguration.EvictionPolicyConfigurer
230
257
* @see #compose(EvictionPolicyConfigurer, EvictionPolicyConfigurer)
231
258
*/
232
- protected static EvictionPolicyConfigurer compose (Iterable <EvictionPolicyConfigurer > iterable ) {
259
+ protected static @ Nullable EvictionPolicyConfigurer compose (Iterable <EvictionPolicyConfigurer > iterable ) {
233
260
234
261
EvictionPolicyConfigurer current = null ;
235
262
236
- for (EvictionPolicyConfigurer evictionPolicyConfigurer : nullSafeIterable (iterable )) {
263
+ for (EvictionPolicyConfigurer evictionPolicyConfigurer : CollectionUtils . nullSafeIterable (iterable )) {
237
264
current = compose (current , evictionPolicyConfigurer );
238
265
}
239
266
@@ -249,13 +276,17 @@ protected static EvictionPolicyConfigurer compose(Iterable<EvictionPolicyConfigu
249
276
* @return an {@link EvictionPolicyConfigurer} object implementation composed of
250
277
* multiple {@link EvictionPolicyConfigurer} objects using the Composite Software Design Pattern.
251
278
*/
252
- protected static EvictionPolicyConfigurer compose (EvictionPolicyConfigurer one , EvictionPolicyConfigurer two ) {
279
+ protected static @ Nullable EvictionPolicyConfigurer compose (@ Nullable EvictionPolicyConfigurer one ,
280
+ @ Nullable EvictionPolicyConfigurer two ) {
253
281
254
282
return one == null ? two
255
- : ( two == null ? one
256
- : new ComposableEvictionPolicyConfigurer (one , two )) ;
283
+ : two == null ? one
284
+ : new ComposableEvictionPolicyConfigurer (one , two );
257
285
}
258
286
287
+ private final EvictionPolicyConfigurer one ;
288
+ private final EvictionPolicyConfigurer two ;
289
+
259
290
/**
260
291
* Constructs a new instance of the {@link ComposableEvictionPolicyConfigurer} initialized with the two
261
292
* {@link EvictionPolicyConfigurer} objects.
@@ -273,19 +304,24 @@ private ComposableEvictionPolicyConfigurer(EvictionPolicyConfigurer one, Evictio
273
304
* @inheritDoc
274
305
*/
275
306
@ Override
276
- public Object configure (Object regionFactoryBean ) {
277
- return this .two .configure (this .one .configure (regionFactoryBean ));
307
+ public Object configure (Object regionBean ) {
308
+ return this .two .configure (this .one .configure (regionBean ));
309
+ }
310
+
311
+ /**
312
+ * @inheritDoc
313
+ */
314
+ @ Override
315
+ public Region <?, ?> configure (Region <?, ?> region ) {
316
+ return this .two .configure (this .one .configure (region ));
278
317
}
279
318
}
280
319
320
+ @ SuppressWarnings ("unused" )
281
321
protected static class EvictionPolicyMetaData implements EvictionPolicyConfigurer {
282
322
283
323
protected static final String [] ALL_REGIONS = new String [0 ];
284
324
285
- private final EvictionAttributes evictionAttributes ;
286
-
287
- private final Set <String > regionNames = new HashSet <>();
288
-
289
325
protected static EvictionPolicyMetaData from (@ NonNull AnnotationAttributes evictionPolicyAttributes ,
290
326
@ NonNull ApplicationContext applicationContext ) {
291
327
@@ -347,6 +383,10 @@ protected static Integer resolveThreshold(int maximum, EvictionPolicyType type)
347
383
return EvictionPolicyType .HEAP_PERCENTAGE .equals (type ) ? null : maximum ;
348
384
}
349
385
386
+ private final EvictionAttributes evictionAttributes ;
387
+
388
+ private final Set <String > regionNames = new HashSet <>();
389
+
350
390
/**
351
391
* Constructs an instance of {@link EvictionPolicyMetaData} initialized with the given
352
392
* {@link EvictionAttributes} applying to all {@link Region Regions}.
@@ -371,25 +411,11 @@ protected EvictionPolicyMetaData(EvictionAttributes evictionAttributes) {
371
411
*/
372
412
protected EvictionPolicyMetaData (EvictionAttributes evictionAttributes , String [] regionNames ) {
373
413
374
- this .evictionAttributes = Optional .ofNullable (evictionAttributes ).orElseThrow (() ->
375
- newIllegalArgumentException ("EvictionAttributes are required" ));
376
-
377
- Collections .addAll (this .regionNames , nullSafeArray (regionNames , String .class ));
378
- }
414
+ Assert .notNull (evictionAttributes , "EvictionAttributes must not be null" );
379
415
380
- /**
381
- * Returns an instance of the {@link EvictionAttributes} specifying the Eviction policy configuration
382
- * captured in this Eviction policy meta-data.
383
- *
384
- * @return an instance of the {@link EvictionAttributes} specifying the {@link Region}
385
- * Eviction policy configuration.
386
- * @throws IllegalStateException if the {@link EvictionAttributes} were not properly initialized.
387
- * @see org.apache.geode.cache.EvictionAttributes
388
- */
389
- protected EvictionAttributes getEvictionAttributes () {
416
+ this .evictionAttributes = evictionAttributes ;
390
417
391
- return Optional .ofNullable (this .evictionAttributes ).orElseThrow (() ->
392
- newIllegalStateException ("EvictionAttributes was not properly configured and initialized" ));
418
+ Collections .addAll (this .regionNames , ArrayUtils .nullSafeArray (regionNames , String .class ));
393
419
}
394
420
395
421
/**
@@ -401,10 +427,23 @@ protected EvictionAttributes getEvictionAttributes() {
401
427
* @see #resolveRegionName(Object)
402
428
* @see #accepts(Supplier)
403
429
*/
404
- protected boolean accepts (Object regionFactoryBean ) {
430
+ protected boolean accepts (@ Nullable Object regionFactoryBean ) {
405
431
return isRegionFactoryBean (regionFactoryBean ) && accepts (() -> resolveRegionName (regionFactoryBean ));
406
432
}
407
433
434
+ /**
435
+ * Determines whether the given {@link Region} is accepted for Eviction policy configuration.
436
+ *
437
+ * @param region {@link Region} evaluated for Eviction policy configuration.
438
+ * @return a boolean value indicating whether the given {@link Region} is accepted for
439
+ * Eviction policy configuration.
440
+ * @see org.apache.geode.cache.Region
441
+ * @see #accepts(Supplier)
442
+ */
443
+ protected boolean accepts (@ Nullable Region <?, ?> region ) {
444
+ return region != null && accepts (() -> region .getName ());
445
+ }
446
+
408
447
/**
409
448
* Determine whether the {@link Region} identified by name is accepted for Eviction policy configuration.
410
449
*
@@ -425,7 +464,7 @@ protected boolean accepts(Supplier<String> regionName) {
425
464
protected String resolveRegionName (Object regionFactoryBean ) {
426
465
427
466
return regionFactoryBean instanceof ResolvableRegionFactoryBean
428
- ? ((ResolvableRegionFactoryBean ) regionFactoryBean ).resolveRegionName ()
467
+ ? ((ResolvableRegionFactoryBean <?, ?> ) regionFactoryBean ).resolveRegionName ()
429
468
: null ;
430
469
}
431
470
@@ -447,12 +486,59 @@ protected EvictingRegionFactoryBean setEvictionAttributes(EvictingRegionFactoryB
447
486
return regionFactoryBean ;
448
487
}
449
488
489
+ /**
490
+ * Returns an instance of the {@link EvictionAttributes} specifying the Eviction policy configuration
491
+ * captured in this Eviction policy meta-data.
492
+ *
493
+ * @return an instance of the {@link EvictionAttributes} specifying the {@link Region}
494
+ * Eviction policy configuration.
495
+ * @throws IllegalStateException if the {@link EvictionAttributes} were not properly initialized.
496
+ * @see org.apache.geode.cache.EvictionAttributes
497
+ */
498
+ protected EvictionAttributes getEvictionAttributes () {
499
+
500
+ return Optional .ofNullable (this .evictionAttributes ).orElseThrow (() ->
501
+ newIllegalStateException ("EvictionAttributes was not properly configured and initialized" ));
502
+ }
503
+
504
+ /**
505
+ * @inheritDoc
506
+ */
450
507
@ Override
451
- public Object configure (Object regionFactoryBean ) {
508
+ public Object configure (Object regionBean ) {
509
+
510
+ return accepts (regionBean )
511
+ ? setEvictionAttributes ((EvictingRegionFactoryBean ) regionBean )
512
+ : regionBean ;
513
+ }
514
+
515
+ /**
516
+ * @inheritDoc
517
+ */
518
+ @ Override
519
+ public Region <?, ?> configure (Region <?, ?> region ) {
520
+
521
+ Optional .ofNullable (region )
522
+ .filter (this ::accepts )
523
+ .filter (this ::isDefaultEvictionEntryMaximum )
524
+ .map (Region ::getAttributesMutator )
525
+ .map (AttributesMutator ::getEvictionAttributesMutator )
526
+ .ifPresent (evictionAttributesMutator ->
527
+ evictionAttributesMutator .setMaximum (getEvictionAttributes ().getMaximum ()));
528
+
529
+ return region ;
530
+ }
531
+
532
+ private boolean isDefaultEvictionEntryMaximum (Region <?, ?> region ) {
533
+ return region != null && isDefaultEvictionEntryMaximum (region .getAttributes ());
534
+ }
535
+
536
+ private boolean isDefaultEvictionEntryMaximum (RegionAttributes <?, ?> regionAttributes ) {
537
+ return regionAttributes != null && isDefaultEvictionEntryMaximum (regionAttributes .getEvictionAttributes ());
538
+ }
452
539
453
- return accepts (regionFactoryBean )
454
- ? setEvictionAttributes ((EvictingRegionFactoryBean ) regionFactoryBean )
455
- : regionFactoryBean ;
540
+ private boolean isDefaultEvictionEntryMaximum (EvictionAttributes evictionAttributes ) {
541
+ return EvictionAttributes .DEFAULT_ENTRIES_MAXIMUM == evictionAttributes .getMaximum ();
456
542
}
457
543
}
458
544
}
0 commit comments