Skip to content

Commit 09239b7

Browse files
author
Udo Kohlmeyer
committed
DATAGEODE-136 - Adding AsCacheWriter
1 parent dc34bca commit 09239b7

18 files changed

+686
-75
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2016-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package org.springframework.data.gemfire.config.annotation;
19+
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
25+
import org.springframework.data.gemfire.eventing.config.CacheWriterEventType;
26+
27+
/**
28+
* Used to declare a concrete method as a CacheWriter event handler
29+
*
30+
* @author Udo Kohlmeyer
31+
* @since 2.3.0
32+
*/
33+
@Retention(RetentionPolicy.RUNTIME)
34+
@Target({ ElementType.METHOD })
35+
public @interface AsCacheWriter {
36+
37+
/**
38+
* An array of {@link CacheWriterEventType} that control what region CRUD events need to be observed
39+
* {@link CacheWriterEventType} and {@link RegionCacheWriterEventType} cannot be set on the same method. As they
40+
* are mutually exclusive and require that the implementing method uses {@link org.apache.geode.cache.RegionEvent} or
41+
* {@link org.apache.geode.cache.EntryEvent}
42+
*/
43+
CacheWriterEventType[] eventTypes() default {};
44+
45+
/**
46+
* An array for {@link org.apache.geode.cache.Region} names which this {@link org.apache.geode.cache.CacheWriter}
47+
* will be link to. Not declaring any regions will result in the CacheWriter to be configured against all defined
48+
* regions.
49+
*/
50+
String[] regions() default {};
51+
}

spring-data-geode/src/main/java/org/springframework/data/gemfire/config/annotation/AsRegionEventListener.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424

2525
import org.springframework.data.gemfire.eventing.config.CacheListenerEventType;
2626
import org.springframework.data.gemfire.eventing.config.RegionCacheListenerEventType;
27+
import org.springframework.data.gemfire.eventing.config.CacheWriterEventType;
28+
import org.springframework.data.gemfire.eventing.config.RegionCacheWriterEventType;
2729

2830
/**
29-
* Used to declare a concrete method as a RegionEventListener event handler, which handles {@link org.apache.geode.cache.Region}
31+
* Used to declare a concrete method as a RegionEventListener event handler,
32+
* which handles {@link org.apache.geode.cache.Region}
3033
*
3134
* @author Udo Kohlmeyer
3235
* @since 2.3.0
@@ -41,10 +44,18 @@
4144
* are mutually exclusive and require that the implementing method uses {@link org.apache.geode.cache.RegionEvent} or
4245
* {@link org.apache.geode.cache.EntryEvent}
4346
*/
44-
RegionCacheListenerEventType[] regionEventTypes() default {};
47+
RegionCacheListenerEventType[] regionListenerEventTypes() default {};
4548

4649
/**
47-
* An array for {@link org.apache.geode.cache.Region} names which this {@link org.apache.geode.cache.CacheListener}
50+
* An array of {@link RegionCacheWriterEventType} that control what region events need to be observed.
51+
* {@link CacheWriterEventType} and {@link RegionCacheWriterEventType} cannot be set on the same method. As they
52+
* are mutually exclusive and require that the implementing method uses {@link org.apache.geode.cache.RegionEvent} or
53+
* {@link org.apache.geode.cache.EntryEvent}
54+
*/
55+
RegionCacheWriterEventType[] regionWriterEventTypes() default {};
56+
57+
/**
58+
* An array for {@link org.apache.geode.cache.Region} names which this {@link org.apache.geode.cache.CacheWriter}
4859
* will be link to. Not declaring any regions will result in the CacheListener to be configured against all defined
4960
* regions.
5061
*/
+13-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
package org.springframework.data.gemfire.eventing.config;
18+
package org.springframework.data.gemfire.config.annotation;
1919

2020
import java.lang.annotation.Documented;
2121
import java.lang.annotation.ElementType;
@@ -25,22 +25,30 @@
2525
import java.lang.annotation.Target;
2626

2727
import org.springframework.context.annotation.Import;
28+
import org.springframework.data.gemfire.eventing.config.AsCacheListenerBeanPostProcessorRegistrar;
29+
import org.springframework.data.gemfire.eventing.config.AsCacheWriterBeanPostProcessorRegistrar;
30+
import org.springframework.data.gemfire.eventing.config.PojoCacheListenerWrapper;
31+
import org.springframework.data.gemfire.eventing.config.PojoCacheWriterWrapper;
2832

2933
/**
3034
* Enables GemFire annotated EventHandler implementations. These implementation will include {@link org.apache.geode.cache.CacheListener},
3135
* {@link org.apache.geode.cache.CacheWriter}, {@link org.apache.geode.cache.TransactionListener} and {@link org.apache.geode.cache.CacheLoader}
3236
*
33-
* This annotation results in the container discovering any beans that are annotated with {code}@AsCacheListener{code},
34-
* wraps them in a {@link PojoCacheListenerWrapper} and register them with the corresponding {@link org.apache.geode.cache.Region}.
35-
*
37+
* This annotation results in the container discovering any beans that are annotated with:
38+
* <ul><
39+
* <li> {code}@AsCacheListener{code},wraps them in a {@link PojoCacheListenerWrapper}</li>
40+
* <li> {code}@AsCacheWriter{code},wraps them in a {@link PojoCacheWriterWrapper}</li>
41+
* <li></li>and register them with the corresponding {@link org.apache.geode.cache.Region}.
42+
*</ul>
3643
* @author Udo Kohlmeyer
3744
* @since 2.3.0
3845
*/
3946
@Target(ElementType.TYPE)
4047
@Retention(RetentionPolicy.RUNTIME)
4148
@Inherited
4249
@Documented
43-
@Import(AsCacheListenerBeanPostProcessorRegistrar.class)
50+
@Import({ AsCacheListenerBeanPostProcessorRegistrar.class,
51+
AsCacheWriterBeanPostProcessorRegistrar.class})
4452
@SuppressWarnings("unused")
4553
public @interface EnableEventProcessing {
4654

spring-data-geode/src/main/java/org/springframework/data/gemfire/config/support/CacheListenerPostProcessor.java

+18-42
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import java.lang.annotation.Annotation;
2525
import java.lang.reflect.Method;
26-
import java.lang.reflect.Modifier;
2726
import java.util.ArrayList;
2827
import java.util.List;
2928
import java.util.Optional;
@@ -40,63 +39,43 @@
4039
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
4140
import org.springframework.context.annotation.Configuration;
4241
import org.springframework.core.annotation.AnnotationAttributes;
43-
import org.springframework.core.annotation.AnnotationUtils;
4442
import org.springframework.data.gemfire.config.annotation.AsCacheListener;
4543
import org.springframework.data.gemfire.config.annotation.AsRegionEventListener;
4644
import org.springframework.data.gemfire.eventing.EventProcessorUtils;
4745
import org.springframework.data.gemfire.eventing.config.CacheListenerEventType;
4846
import org.springframework.data.gemfire.eventing.config.PojoCacheListenerWrapper;
4947
import org.springframework.data.gemfire.eventing.config.PojoRegionEventCacheListenerWrapper;
5048
import org.springframework.data.gemfire.eventing.config.RegionCacheListenerEventType;
51-
import org.springframework.data.gemfire.util.ArrayUtils;
5249
import org.springframework.util.Assert;
5350
import org.springframework.util.ObjectUtils;
54-
import org.springframework.util.ReflectionUtils;
5551

5652
/**
5753
* A {@link BeanPostProcessor} to create and register {@link CacheListener}, annotated with {@link AsCacheListener}
5854
* and {@link AsRegionEventListener} onto the configured {@link Region}s
5955
*/
60-
@Configuration public class CacheListenerPostProcessor implements BeanPostProcessor, BeanFactoryAware {
56+
@Configuration
57+
public class CacheListenerPostProcessor extends CallbackPostProcessor
58+
implements BeanPostProcessor, BeanFactoryAware {
6159

6260
private ConfigurableListableBeanFactory beanFactory;
6361

64-
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
65-
66-
registerAnyDeclaredCacheListenerAnnotatedMethods(bean, AsCacheListener.class);
67-
registerAnyDeclaredCacheListenerAnnotatedMethods(bean, AsRegionEventListener.class);
68-
69-
return bean;
62+
@Override
63+
protected Class getRegionCallbackClass() {
64+
return AsRegionEventListener.class;
7065
}
7166

72-
private <T extends Annotation> void registerAnyDeclaredCacheListenerAnnotatedMethods(Object bean,
73-
Class<T> listenerAnnotationClazz) {
74-
75-
stream(nullSafeArray(ReflectionUtils.getAllDeclaredMethods(bean.getClass()), Method.class)).forEach(method -> {
76-
77-
Optional<T> cacheListenerAnnotation = Optional.ofNullable(AnnotationUtils
78-
.getAnnotation(method, listenerAnnotationClazz));
79-
80-
cacheListenerAnnotation.ifPresent(asCacheListener -> {
81-
82-
Assert.isTrue(Modifier.isPublic(method.getModifiers()), String
83-
.format("The bean [%s] method [%s] annotated with [%s] must be public", bean.getClass().getName(),
84-
method.getName(), listenerAnnotationClazz.getName()));
85-
86-
AnnotationAttributes cacheListenerAttributes = resolveAnnotationAttributes(asCacheListener);
87-
88-
registerEventHandlers(bean, listenerAnnotationClazz, method, cacheListenerAttributes);
89-
90-
});
91-
});
67+
@Override
68+
protected Class getCallbackClass() {
69+
return AsCacheListener.class;
9270
}
9371

94-
private <T extends Annotation> void registerEventHandlers(Object bean, Class<T> listenerAnnotationClazz,
72+
@Override
73+
protected <T extends Annotation> void registerEventHandlers(Object bean, Class<T> listenerAnnotationClazz,
9574
Method method, AnnotationAttributes cacheListenerAttributes) {
96-
if (listenerAnnotationClazz.isAssignableFrom(AsCacheListener.class)) {
75+
if (listenerAnnotationClazz.isAssignableFrom(getCallbackClass())) {
9776
registerCacheListenerEventHandler(bean, method, cacheListenerAttributes);
9877
}
99-
else if (listenerAnnotationClazz.isAssignableFrom(AsRegionEventListener.class)) {
78+
else if (listenerAnnotationClazz.isAssignableFrom(getRegionCallbackClass())) {
10079
registerRegionEventHandler(bean, method, cacheListenerAttributes);
10180
}
10281
}
@@ -122,7 +101,7 @@ private void registerCacheListenerEventHandler(Object bean, Method method,
122101
private void registerRegionEventHandler(Object bean, Method method,
123102
AnnotationAttributes cacheListenerAttributes) {
124103
RegionCacheListenerEventType[] eventTypes = (RegionCacheListenerEventType[]) cacheListenerAttributes
125-
.get("regionEventTypes");
104+
.get("regionListenerEventTypes");
126105
registerEventHandlerToRegion(method, cacheListenerAttributes,
127106
new PojoRegionEventCacheListenerWrapper(method, bean, eventTypes), RegionEvent.class);
128107
}
@@ -142,7 +121,7 @@ private <T extends CacheEvent> void registerEventHandlerToRegion(Method method,
142121
String[] regions = getRegionsForEventRegistration(cacheListenerAttributes.getStringArray("regions"),
143122
getBeanFactory());
144123

145-
EventProcessorUtils.validateCacheListenerMethodParameters(method, eventClass);
124+
EventProcessorUtils.validateEventHandlerMethodParameters(method, eventClass);
146125
EventProcessorUtils.registerCacheListenerToRegions(regions, beanFactory, cacheListener);
147126
}
148127

@@ -174,11 +153,6 @@ private String[] getRegionsForEventRegistration(String[] regions, ConfigurableLi
174153
}
175154
}
176155

177-
private AnnotationAttributes resolveAnnotationAttributes(Annotation annotation) {
178-
179-
return AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes(annotation, false, true));
180-
}
181-
182156
/**
183157
* Returns a reference to the containing Spring {@link BeanFactory}.
184158
*
@@ -200,7 +174,9 @@ protected ConfigurableListableBeanFactory getBeanFactory() {
200174
* @see org.springframework.beans.factory.BeanFactoryAware
201175
* @see org.springframework.beans.factory.BeanFactory
202176
*/
203-
@Override @SuppressWarnings("all") public final void setBeanFactory(BeanFactory beanFactory) throws BeansException {
177+
@Override
178+
@SuppressWarnings("all")
179+
public final void setBeanFactory(BeanFactory beanFactory) throws BeansException {
204180

205181
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory, String
206182
.format("BeanFactory [%1$s] must be an instance of %2$s", ObjectUtils.nullSafeClassName(beanFactory),

0 commit comments

Comments
 (0)