#spring-boot #spring-data-gemfire
#spring-boot #spring-data-gemfire
Вопрос:
Могу ли я узнать, как реализовать GemFire / Geode CacheListener
в моем приложении Spring Boot?
Я хочу обнаруживать удаление и обновлять в моем регионе «Люди». Я использую org.springframework.data:зависимость spring-data-gemfire в Maven. Нужно ли мне включать какие-либо аннотации?
@SpringBootApplication
@ClientCacheApplication(name = "AccessingDataGemFireApplication", logLevel = "error")
@EnableEntityDefinedRegions(basePackageClasses = People.class)
@EnableGemfireRepositories
public class Application
{
....
}
Ответ №1:
По-видимому, в последней версии GA CacheListener
по-прежнему отсутствует поддержка аннотаций для обратных вызовов GemFire ( CacheLoader
, spring-data-gemfire
и т.д.). Некоторое время назад для реализации этого улучшения был создан тикет JIRA SGF-453, вы можете добавить себя в качестве наблюдателя, чтобы получать обновления о ходе выполнения.
Однако вы можете вручную связать a CacheListener
с регионом, используя cache-listener
элемент xml, как показано в документации. Или, еще один вариант, вы можете настроить прослушиватель непосредственно через API с помощью RegionFactoryBean.setListeners
.
В качестве примера следующий класс запускает локальный сервер GemFire со встроенным локатором, создает REPLICATED
регион с именем People
и связывает с ним пользовательский CacheListener
, который в основном выводит сообщение каждый раз, когда создается или удаляется запись:
@EnableLogging
@EnableStatistics
@SpringBootApplication
@CacheServerApplication
public class GemFireServerApplication {
public static void main(String[] args) {
SpringApplication.run(GemFireServerApplication.class, args);
}
@EnableLocator
@Profile("!clustered")
@EnableManager(start = true)
@Configuration
static class LonerConfiguration { }
@Bean("People")
public ReplicatedRegionFactoryBean<?, ?> replicatedRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<?, ?> replicatedRegion = new ReplicatedRegionFactoryBean<>();
replicatedRegion.setCache(gemfireCache);
replicatedRegion.setClose(false);
replicatedRegion.setPersistent(false);
replicatedRegion.setCacheListeners(new CacheListener[] { myCacheListener() });
return replicatedRegion;
}
@Bean
public CacheListener<?, ?> myCacheListener() {
return new CacheListenerAdapter<String, String>() {
@Override
public void afterDestroy(EntryEvent<String, String> event) {
System.out.println(String.format("AfterDestroy invoked for key %s !", event.getKey()));
super.afterDestroy(event);
}
@Override
public void afterCreate(EntryEvent<String, String> event) {
System.out.println(String.format("AfterCreate invoked for key %s !", event.getKey()));
super.afterCreate(event);
}
};
}
}
Надеюсь, это поможет. Приветствия.
Ответ №2:
Поскольку вы используете более удобную @EnableEntityDefinedRegions
аннотацию SDG (которая рекомендуется, особенно для простого UC), то вы явно не определяете определение компонента Region (например, используя ReplicationRegionFactoryBean
или PartitionedRegionFactoryBean
классы SDG), как это сделал Хуан Рамос в своем ответе.
В этом случае вы можете объявить a RegionConfigurer
для изменения региона «Люди», а затем применить ту же технику, которую Хуан использовал в своем ответе, для предоставления CacheListener
.
Например:
@SpringBootApplication
@EnableEntityDefinedRegions(basePackageClasses = People.class)
@EnableGemfireRepositories(..)
class MySpringBootGemFireApplication {
@Bean
RegionConfigurer peopleRegionConfigurer(
CacheListener<Long, Person> peopleRegionListener) {
return new RegionConfigurer() {
@Override
public void configure(String beanName,
ClientRegionFactoryBean<Long, Person> regionFactory) {
regionFactoryBean.setCacheListeners(
new CacheListener[] { peopleRegionListener });
};
}
@Bean
CacheListenerAdapter<Long, Person> peopleRegionListener() {
return new CacheListenerAdapter<>() {
public void afterDestroy(EntryEvent<Long, Person> event) { ... }
public void afterUpdate(EntryEvent<Long, Person> event) { ... }
};
}
}
ПРИМЕЧАНИЕ: при использовании Spring Boot, GemFire Starter ( org.springframework.geode:spring-gemfire-starter
), @ClientCacheApplication
аннотация определенно не требуется, поскольку SBDG автоматически настраивает ClientCache
экземпляр по умолчанию (см. Здесь).
Примечание: Кроме того, если ваше приложение GemfireRepositories
находится в подпакете ниже основного класса Spring Boot application, вам также не нужно явно объявлять @EnableGemfireRepositories
, поскольку SBDG автоматически настраивает инфраструктуру хранилища SD для вас (см. Здесь).
Для получения дополнительной информации о конфигураторах SDG смотрите здесь.
Надеюсь, это поможет.
Комментарии:
1. Когда я попробовал ваше решение, мой компилятор выдал мне следующее: «Целевой тип этого выражения должен быть функциональным интерфейсом» в строке «return (beanName, regionFactoryBean)». Поскольку это метод по умолчанию. Я думаю, что лямбды не позволяют переопределять методы по умолчанию. Есть ли способ решить эту проблему?
2. Приношу свои извинения. На самом деле, это потому, что
RegionConfigurer
интерфейс ( docs.spring.io/spring-data/geode/docs/current/api/org / … ) не являетсяFunctionalInterface
. Интерфейс определяет 2 метода по умолчанию, 1 сClientRegionFactoryBean
для определения клиентских регионов, а другой сPeerRegionFactoryBean
при определении серверных регионов. Следовательно, вы должны точно указывать, какой метод вы «переопределяете», и поэтому _Lambda) не работает для этого интерфейса в отличие от других предоставляемых SDGConfigurers
.3. Я исправил свой пример выше. Вы можете увидеть другой пример
RegionConfigurer
из набора тестов SDG, здесь ( github.com/spring-projects/spring-data-geode/blob/master/src / … ). Технически вам нужно переопределить только 1 из 2 методов в зависимости от того, является ли ваше приложение «клиентом» или фактическим «одноранговым узлом» в кластере. Учитывая, что вы используете@ClientCacheApplication
, вам следует переопределить метод client, как показано в моем измененном примере выше.4. Большое вам спасибо.