Search code examples
gemfirespring-data-gemfire

Gemfire PDX error on startup : The PDX metadata has already been created as a peer metadata region. Please create your pools first


I am very new to gemfire and I am having trouble starting my application with it.

The error I get is

[info 2015/05/22 10:55:39.746 BRT  <localhost-startStop-1> tid=0xf] Marking DistributionManager <v0>:17758 as closed.
10:55:40.922 [localhost-startStop-1] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gfPool': Invocation of init method failed; nested exception is com.gemstone.gemfire.pdx.PdxInitializationException: The PDX metadata has already been created as a peer metadata region. Please create your pools first
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:743) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) ~[spring-context-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4728) [catalina.jar:8.0.21]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166) [catalina.jar:8.0.21]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:8.0.21]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409) [catalina.jar:8.0.21]
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399) [catalina.jar:8.0.21]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_45]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_45]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_45]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
Caused by: com.gemstone.gemfire.pdx.PdxInitializationException: The PDX metadata has already been created as a peer metadata region. Please create your pools first
    at com.gemstone.gemfire.pdx.internal.PeerTypeRegistration.creatingPool(PeerTypeRegistration.java:501) ~[gemfire-8.0.0.jar:?]
    at com.gemstone.gemfire.pdx.internal.TypeRegistry.creatingPool(TypeRegistry.java:273) ~[gemfire-8.0.0.jar:?]
    at com.gemstone.gemfire.internal.cache.PoolFactoryImpl.create(PoolFactoryImpl.java:439) ~[gemfire-8.0.0.jar:?]
    at org.springframework.data.gemfire.client.PoolFactoryBean.afterPropertiesSet(PoolFactoryBean.java:172) ~[spring-data-gemfire-1.6.0.RELEASE.jar:1.6.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562) ~[spring-beans-4.1.4.RELEASE.jar:4.1.4.RELEASE]
    ... 21 more

Here is my config

gemfire-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gfe="http://www.springframework.org/schema/gemfire"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.2.xsd">

     <gfe:client-cache id="gemfireClientCache"
        cache-xml-location="classpath:client.xml" pool-name="gfPool" use-bean-factory-locator="false" />

    <gfe:pool id="gfPool" max-connections="10">
        <gfe:locator host= "127.0.0.1" port="9980" />                   
    </gfe:pool>

    <gfe:lookup-region id="myRegion" name="myRegion" cache-ref="gemfireClientCache" />


</beans>  

Here is Client.xml

 <pdx read-serialized="false">
    <pdx-serializer>
        <class-name>com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer</class-name>
        <parameter name="classes">
            <string>br.com.xxx.*</string>
        </parameter>
        <parameter name="check-portability">
            <string>true</string>
        </parameter>
    </pdx-serializer>
</pdx>
<region name="myRegion">
    <region-attributes refid="PROXY" />
</region>

My applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gfe="http://www.springframework.org/schema/gemfire"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd


http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <!-- Use this configuration to test locally -->

    <gfe:cache id="gemfireCache" pdx-persistent="true"/>

    <gfe:partitioned-region id="myRegion" data-policy="PARTITION"/>

    <import resource="classpath:registry-gemfire-context.xml"/>

    <import resource="classpath:br/com/xxx/context.xml"/>

    <context:component-scan base-package="br.com.xxx.*"/>

    <bean id="string" class="java.lang.String"/>

</beans>

Solution

  • Agreed, the error message was perhaps not all that useful, but then this was a GemFire-specific Exception (i.e. PdxInitializationException) and error message.

    Also, a few tips here...

    1. You do not need to explicitly give <gfe:cache> or <gfe:client-cache> and <gfe:pool> an ID if you do not plan to change the defaults, which SDG sets in the XML namespace corresponding to the constants defined in... https://github.com/spring-projects/spring-data-gemfire/blob/master/src/main/java/org/springframework/data/gemfire/config/GemfireConstants.java#L27-31.

    In this way, any client-side Region will automatically get assigned the 1 and only Pool in your configuration appropriately, providing, as @dturanski stated, you forgoe the native GemFire XML configuration and define your client Region as so...

    <gfe:client-region id="myRegion" shortcut="PROXY"/>
    

    Then "myRegion" is automatically associated with the ClientCache and client Pool.

    1. You also do not need to explicitly set the DataPolicy on your server-side PARTITION Region...

    Since <gfe:partitioned-region> without the persistent attribute set to true (defaults to false) implies PARTITION (i.e. it is redundant).

    1. You can also define PDX Serialization on a ClientCache using the element. See the XML namespace for further details.

    2. Finally, while you did the right thing in your Spring config on the server-side, explicitly declaring the <context:component-scan> element after the GemFire configuration, be sure to continue to do this otherwise you may run into unexpected behavior down the road as your use case and requirements grow, especially if you are injecting Regions into, say DAOs (rather than using the SDG Repository abstraction), for instance.

    In fact, it maybe wiser to separate out the GemFire configuration from your application configuration altogether and rely on imports as you have done with

    registry-gemfire-context.xml, and... br/com/xxx/context.xml

    GemFire is a complex animal, so keeping things encapsulated, organized and simple is the key to success with GemFire.

    Hope this helps; cheers!