0

I am migrating my GemFire cluster from 8.2.7 (with Spring Data GemFire 1.6.0.RELEASE) to Pivotal GemFire 9.3.0 (SDG 2.0.7.RELEASE). I was using spring-context.xml (declared under the initializer tag in cache.xml) to initialize the Regions while starting cache servers on each node.

When I try to reuse the same spring-context.xml for Pivotal GemFire 9.3.0, my Spring beans tag is not identified by the gfsh command and I am getting following exception:

Caused by: org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 107; cvc-elt.1: Cannot find the declaration of element 'beans'.

        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)

        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)

spring-context.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:gfe="http://www.springframework.org/schema/geode"
       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/geode http://www.springframework.org/schema/gemfire/spring-geode.xsd
                http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:properties id="gemfireProperties">
        <prop key="log-level">config</prop>
        <prop key="locators">hostA[10334],hostB[10334]</prop>
    </util:properties>

    <bean id="mappingPdxSerializer" class="org.springframework.data.gemfire.mapping.MappingPdxSerializer"/>

    <gfe:cache properties-ref="gemfireProperties" pdx-serializer-ref="mappingPdxSerializer"/>

    <gfe:replicated-region id="Product">
    </gfe:replicated-region>

    <gfe:replicated-region id="ProductCustomer">
    </gfe:replicated-region>

</beans>

I updated the XML schema paths from "gemfire" to "geode" based on Spring documentation for spring-data-gemfire:2.0.7.RELEASE.

Trying with GF 9.1.1 and SDGF 2.0.7. (SDGF jar is placed in lib)

Script:

#!/bin/sh
export PATH=$PATH:/var/tmp/user/gemfire/9.1.1:/opt/jdk/1.8.0_71l64/bin/:/var/tmp/user/gemfire/9.1.1/bin/
export GEMFIRE=/var/tmp/user/gemfire/9.1.1/


for i in `ls  /var/tmp/user/gemfire/9.1.1/lib/*.jar`
do
  CLASSPATH=${CLASSPATH}:${i}
done
CLASSPATH=$CLASSPATH:/var/tmp/user/gemfire/9.1.1/config
#echo $CLASSPATH

if [ -e "/var/tmp/user/gemfire/9.1.1/config/spring-context.xml" ]; then
   echo "File exists"
else
 echo "File does not exist"
fi


gfsh start server --name=server1 --server-port=40405 --classpath=$CLASSPATH --spring-xml-location=/var/tmp/user/gemfire/9.1.1/config/spring-context.xml  --locators=hostA[10334],hostB[10334] --mcast-port=0

UPDATE:

FileNotFoundException thrown :

Caused by: java.io.FileNotFoundException: class path resource [var/tmp/sn17180/gemfire/9.1.1/config/spring-context.xml] cannot be opened because it does not exist

        at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)

        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)

        ... 17 more

I have given permission to all the files and -e "/" in my script is also printing "File exists".

UPDATE:

cache.xml

<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://geode.apache.org/schema/cache http://geode.apache.org/schema/cache/cache-1.0.xsd"
       version="1.0">

  <region name="Parent" refid="REPLICATE">
    <region name="Child" refid="REPLICATE"/>
  </region>

</cache>

gemfire-config.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="locators">xyz[10334],xyx[10334]</prop>
        <prop key="mcast-port">0</prop>
    </util:properties>

    <bean id="autoSerializer" class="org.apache.geode.pdx.ReflectionBasedAutoSerializer"/>

    <gfe:cache properties-ref="gemfireProperties" cache-xml-location="cache.xml" pdx-serializer-ref="autoSerializer" pdx-read-serialized="true"/>   

</beans>
John Blum
  • 7,381
  • 1
  • 20
  • 30
Sudharsan
  • 207
  • 1
  • 2
  • 12

1 Answers1

1

Pivotal GemFire stopped shipping with Spring Data GemFire in the $GEMFIRE_HOME/lib directory as of the 9.x release series. There are 2 primary reasons for this.

1) First, it was somewhat of a conundrum that Pivotal GemFire depended on SDG, which was entirely for gfsh>start server --name=SpringConfiguredServer --spring-xml-location-/path/to/spring/context.xml, when SDG depended on Pivotal GemFire, which clearly forms a circular dependency.

2) Pivotal GemFire lags significantly behind the current state of the Spring ecosystem when it pertains to versions. Even the latest release, 9.3.0, ships with outdated Spring JARs, e.g. core Spring Framework 4.3.13.RELEASE, when core Spring Framework 4.3.17.RELEASE is already available as well as 5.0.6.RELEASE, with 5.1 on the horizon.

Having said that, it is still possible to configure and bootstrap your Pivotal GemFire Servers with Spring when started from Gfsh using the start server command, --spring-xml-location option. You simply need to download the appropriate version of SDG based on the Pivotal GemFire version you are using (e.g. (9.3.0)) and put SDG on the classpath when starting the server.

NOTE: currently, SDG 2.1.0.M3 (SD Lovelace) is the only version based on Pivotal GemFire 9.3 and later; currently set to 9.5.0.

NOTE: also not, I don't specifically recall whether I ran into any API breaking changes between upgrading SDG Lovelace progressively from Pivotal GemFire 9.3, then to 9.4 and finally arriving at 9.5. If you have trouble with spring-data-gemfire:2.1.0.M3, you can also use spring-data-gemfire:2.1.0.M2 which was based on Pivotal GemFire 9.3 at the time.

So following the recipe above, you would do the following...

gfsh> start server --name=SpringConfiguredServer --classpath=/file/system/path/to/spring-data-gemfire22.1.0.M3.jar --spring-xml-location=/classpath/to/your/spring-context.xml

This should work!

Also, you do not need to switch schemas from "gemfire" to "geode". When you are using Spring Data GemFire, then use the "spring-gemfire" schema. When you are using Spring Data Geode, then use the "spring-geode" schema. Either will probably work, but...

Hope this helps!

-j

John Blum
  • 7,381
  • 1
  • 20
  • 30
  • Thanks for the reply John. Now I am trying with Gemfire 9.1.1 and SDGF- 2.0.7. I am getting "file does not exist" IO exception . Please check the updated post. – Sudharsan May 30 '18 at 16:34
  • 1
    Hi Sudharsan - So, as you can see from the _Stack Trace_, the Spring context, by default (a `ClassPathXmlApplicationContext` instance when Spring XML is used) searches for your `spring-context.xml` in the CLASSPATH, which matches the ApplicationContext type. This is why you see the `o.s.core.io.ClassPathResource` in the _Stack Trace_. I suspect your `spring-context.xml` is coming from the file system, hence... `var/tmp/sn17180/gemfire/9.1.1/config/spring-context.xml`)? In which case, you need to tell Spring this by prefixing the path to `spring-context.xml` with `file:///`. ... – John Blum May 30 '18 at 18:13
  • This effectively overrides the `ApplicationContext` types default resource search location to be other than the "*default*", which, again, for a `ClassPathXmlApplicationContext` is to search the CLASSPATH for the XML config. If the `ApplicationContext` were a `FileSystemXmlApplicationContext`, then Spring would search for the XML config in the file system. However, even though a `ApplicationContext` defaults the resource path based on type, you can override it with the resource specifier, as described in *Table 10 - Resource strings* at this link ... – John Blum May 30 '18 at 18:18
  • 1
    https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources-resourceloader – John Blum May 30 '18 at 18:18
  • So, I think in your case, the URL to `spring-context.xml` would be... `file:///var/tmp/sn17180/gemfire/9.1.1/config/spring-context.xml`. Note, a ClassPathXmlApplicationContext instance will still be used, but the `file://` resource specifier tells the context to search the file system instead of the CLASSPATH (the default). Hope this helps. – John Blum May 30 '18 at 18:20
  • Thank you so much John for all the explanation. I got it worked. – Sudharsan May 30 '18 at 19:37
  • John. Hope you are doing great. Can I give spring-xml-location property in gemfire.properties?. I am able to find cache xml property from the pivotal docs but not for doing context. Please help. – Sudharsan Apr 23 '19 at 00:19
  • Not `spring-xml-location`, but you can set `cache-xml-file` (see here: http://gemfire.docs.pivotal.io/97/geode/reference/topics/gemfire_properties.html). Of course, above, you are using SDG's GFE namespace so you could simply set ``, too. :) – John Blum Apr 23 '19 at 05:56
  • John. if the cluster config bootstrap cache through cache.xml , can peer or client instance access the same cache and regions through SDGF? – Sudharsan Apr 23 '19 at 14:33
  • The cache is a Singleton, always. So, it does not matter if the cache is created by GemFire native APIs, `cache.xml` or Spring config. To access the Regions created by `cache.xml`, have a look at: https://docs.spring.io/spring-data/geode/docs/current/reference/html/#bootstrap:region:lookup:auto. This also works when your application is a peer cache member in the cluster and you have enabled the Cluster Configuration Service in the Locator and peers. – John Blum Apr 23 '19 at 14:40
  • ok thanks. updated the post with cache.xml and gemfire-config.xml. When the cache server starts, can i input gemfire-config.xml in "cache-xml-location" gemfire property?. will it bootstrap cache and regions with expected PDX serializer? – Sudharsan Apr 23 '19 at 15:08
  • It cannot find your `cache.xml` (i.e. var/tmp/sn17180/gemfire/9.1.1/config/spring-context.xml) because the Gfsh `start server` command, `--spring-xml-location` option looks in the classpath, first. If you want to find the Spring XML config in the file system, then you need to use 1 of Spring's Resource access schemes (e.g. `file:///var/tmp/sn17180/gemfire/9.1.1/config/spring-context.xml`). See Table 10 in (https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources-resourceloader) for more details. – John Blum Apr 23 '19 at 15:17
  • If my cache server is started through Java API (server launcher), what is the property i should use to give my "spring-context.xml"? – Sudharsan Apr 23 '19 at 15:33
  • Then it would by `spring-xml-location`, or this property on `ServerLauncher` (http://gemfire-97-javadocs.docs.pivotal.io/org/apache/geode/distributed/ServerLauncher.Builder.html#setSpringXmlLocation-java.lang.String-). – John Blum Apr 23 '19 at 16:22