【问题标题】:Spring data gemfire support for subregion cache listener对子区域缓存侦听器的 Spring 数据 gemfire 支持
【发布时间】:2014-08-27 02:18:34
【问题描述】:

我正在尝试使用 Spring-data-gemfire 将我现有的应用程序代码移植到启动 Gemfire。所以我基本上是将我的区域配置从 cache.xml 移动到 spring 上下文中。

使用的版本: 宝石火 6.6.3.2 Spring-data-gemfire-1.3.4 JDK 7

在我需要配置缓存侦听器之前一切正常。一个区域上的简单缓存侦听器可以工作,但我无法让缓存侦听器在子区域上工作。

例如,我有以下区域。我希望在 /User/Details/Address 区域更新时通知 CacheUpdateListener(实现 CacheListener 接口)。我知道 Gemfire 支持它,因为我已经让它以 cache.xml 的方式工作。但是有谁知道我是否可以让它与 Spring-data-gemfire 一起使用。这是我尝试过但没有奏效的方法。

<gfe:replicated-region id="VCCache" name="User" scope="distributed-no-ack">
    <gfe:replicated-region name="Details" scope="distributed-no-ack">
        <gfe:replicated-region name="Address" scope="distributed-ack">
            <gfe:cache-listener>
                <bean class="com.vc.cache.CacheUpdateListener" />
            </gfe:cache-listener>
        </gfe:replicated-region>
    </gfe:replicated-region>
</gfe:replicated-region>    

** 编辑:添加了监听器代码 这里是听者。为了简洁起见,我没有将所有过度使用的函数放在这里。

public class CacheUpdateListener implements CacheListener<Object, Object>
{
private static final Logger LOGGER = LoggerFactory.getLogger(CacheUpdateListener.class);

private String name = "defaultName";

@Override
public void afterCreate(EntryEvent<Object, Object> event)
{
    LOGGER.info("[afterCreate] region [{}] key [{}] created remote [{}] with value [{}]",
            new Object[] { event.getRegion().getFullPath(), event.getKey(), event.isOriginRemote(), event.getNewValue() });
}

@Override
public void afterUpdate(EntryEvent<Object, Object> event)
{
    LOGGER.info("[afterUpdate] region [{}] key [{}] updated remote [{}] with value [{}] old value [{}]",
            new Object[] { event.getRegion().getFullPath(), event.getKey(), event.isOriginRemote(), event.getNewValue(), event.getOldValue() });
}
}

【问题讨论】:

    标签: spring-data gemfire spring-data-gemfire


    【解决方案1】:

    我使用对等缓存子区域创建了一个简单的测试,该子区域具有配置了 SDG 的已注册 CacheListener,并且侦听器按预期被回调。可能还有其他因素或原因导致这对您不起作用...

    1. 不知道您的整个 SDG XML 配置,但可能存在竞争的 GemFire 配置,例如使用本地 GemFire cache.xml 和具有冲突区域定义的 Spring 配置(但您确实声明 afterRegionCreate 正在被调用),例如...

    2.我在测试中使用了 SDG 1.4.0.RELEASE 以及 GemFire 7.0.2.12 和 8。但是,您应该能够使用我的测试和示例 SDG XML 配置来测试您的设置...

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("/subRegionCacheListener.xml")
    @SuppressWarnings("unused")
    public class SubRegionCacheListenerTest {
    
      private static final Stack<EntryEvent<Integer, String>> entryEvents = new Stack<EntryEvent<Integer, String>>();
    
      @Resource(name = "/Parent/Child")
      private Region<Integer, String> child;
    
      @Test
      public void testCacheListenerCallback() {
        assertNotNull("The '/Parent/Child' Cache Sub-Region was not properly configured and initialized!", child);
        assertEquals("Child", child.getName());
        assertEquals("/Parent/Child", child.getFullPath());
        assertTrue(child.isEmpty());
        assertTrue(entryEvents.isEmpty());
    
        child.put(1, "TEST");
    
        assertFalse(child.isEmpty());
        assertEquals(1, child.size());
        assertEquals("TEST", child.get(1));
        assertFalse(entryEvents.isEmpty());
    
        EntryEvent event = entryEvents.pop();
    
        assertNotNull(event);
        assertEquals(1, event.getKey());
        assertNull(event.getOldValue());
        assertEquals("TEST", event.getNewValue());
        assertTrue(entryEvents.isEmpty());
    
        child.put(1, "TESTING");
    
        assertFalse(child.isEmpty());
        assertEquals(1, child.size());
        assertEquals("TESTING", child.get(1));
        assertFalse(entryEvents.isEmpty());
    
        event = entryEvents.pop();
    
        assertNotNull(event);
        assertEquals(1, event.getKey());
        assertEquals("TEST", event.getOldValue());
        assertEquals("TESTING", event.getNewValue());
        assertTrue(entryEvents.isEmpty());
    
        child.remove(1);
    
        assertTrue(child.isEmpty());
    
        event = entryEvents.pop();
    
        assertNotNull(event);
        assertEquals(1, event.getKey());
        assertEquals("TESTING", event.getOldValue());
        assertNull(event.getNewValue());
      }
    
      public static final class SubRegionCacheListener extends CacheListenerAdapter<Integer, String> {
    
        @Override
        public void afterCreate(final EntryEvent<Integer, String> event) {
          entryEvents.push(event);
        }
    
        @Override
        public void afterDestroy(final EntryEvent<Integer, String> event) {
          entryEvents.push(event);
        }
    
        @Override
        public void afterUpdate(final EntryEvent<Integer, String> event) {
          entryEvents.push(event);
        }
      }
    }
    

    以及对应的 SDG XML 配置...

    <?xml version="1.0" encoding="utf-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:gfe="http://www.springframework.org/schema/gemfire"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    ">
    
      <util:properties id="gemfireProperties">
        <prop key="name">SpringGemFirePeerCacheSubRegionCacheListenerTest</prop>
        <prop key="mcast-port">0</prop>
        <prop key="log-level">config</prop>
      </util:properties>
    
      <gfe:cache properties-ref="gemfireProperties"/>
    
      <gfe:replicated-region id="Parent">
        <gfe:replicated-region name="Child">
          <gfe:cache-listener>
            <bean class="org.spring.data.gemfire.cache.SubRegionCacheListenerTest$SubRegionCacheListener"/>
          </gfe:cache-listener>
        </gfe:replicated-region>
      </gfe:replicated-region>
    
    </beans>
    

    希望这会有所帮助。

    很可能,这里可能存在配置问题,或者 GemFire 6.x 可能存在问题(尽管您声明它可以与 GemFire 的 cache.xml 一起使用?)。

    【讨论】:

    • 感谢约翰,感谢您对我的问题的全面回答。我能够通过将 'data-policy="REPLICATE"' 添加到具有 CacheListener 的子区域来解决此问题。所以我的子区域定义现在看起来像 我认为 暗示数据策略是“复制”。此外,由于您的示例没有明确指定数据策略,我假设这已在最新版本中得到修复。
    • 似乎有点熟悉,可能嵌套的 元素(又名 REPLICATE Sub-Regions)数据策略没有得到正确处理。我向 RegionFactoryBean 类(不记得什么版本,1.4.0?)添加了一个新的 resolveDataPolicy(..) 方法,该方法由强类型的 RegionFactoryBean 子类(例如 ReplicatedRegionFactoryBean)实现,以正确设置区域的数据策略。无论如何,是的, 元素应该产生 REPLICATE Regions, 元素应该产生 PARTITION Regions,等等。
    • 你的记忆力很好!我希望能尽快升级,但同时我可以通过这个解决方法来解决问题。谢谢。
    【解决方案2】:

    这应该从 1.3.3 开始工作,请参阅 https://jira.spring.io/browse/SGF-219。如果您确定它不起作用,请向该 JIRA 添加评论。

    【讨论】:

    • 感谢您的指点。但我的问题略有不同。我在上下文加载时没有收到错误,并且 gemfire 启动正常。我什至在 afterRegionCreate() 的同一个侦听器上收到了回叫。但我没有收到 afterCreate() 和 afterUpdate() 的回调
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多