1
votes

I created repository SpringbootGeodeExample for demo purpose.

Started a Locator in Gfsh, and cache server embedded in Spring Boot application with some Regions defined in the Spring context for embedded cache server. Now I can list the Region, but failed to query & destroy Region, execute "describe" Region shows "Hosting Members" is blank.

gfsh>describe region --name=Region1
..........................................................
Name            : Region1
Data Policy     : partition
Hosting Members :

gfsh>query --query="select * from /Region1"
Result  : false
Message : Cannot find regions <[/Region1]> in any of the members

gfsh>destroy region --name=Region1
Could not find a Region with Region path "Region1" in this Geode cluster. If region was recently created, please wait for at least jmx-manager-update-rate milliseconds to allow the associated Management resources to be federated.

I can do above on Regions created in Gfsh, how can I do the same CRUD operations on Regions created in Spring context?

I tried add --enable-cluster-configuration=true and use-cluster-configuration="true" in locator and cache server, but still not working.

More details: Cache server application config:

@SpringBootApplication
@CacheServerApplication
@EnableCacheServer(autoStartup = true, port = 41414)
@ImportResource("classpath:spring-cache-context-cluster-side.xml")
public class CacheServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheServerApplication.class, args);
    }
}

Region definition in spring context:

<gfe:partitioned-region id="Region1" copies="1">
        <gfe:eviction type="MEMORY_SIZE" threshold="512" action="LOCAL_DESTROY"/>
</gfe:partitioned-region>

Update according to comment from John:

Update 1:

List members shows cache server name is blank, is this the root cause?

gfsh>list members
  Name   | Id
-------- | -----------------------------------------------
locator2 | 192.168.1.2(locator2:1396:locator)<ec><v0>:1024
         | 192.168.1.2(6032)<v3>:1025

I tried to change annotations to:

@SpringBootApplication
@CacheServerApplication(name = "MyServer", locators="localhost[10334]", autoStartup = true, port = 41415)
@EnableCacheServer(name = "MyServer", autoStartup = true, port = 41414)
@ImportResource("classpath:spring-cache-context-cluster-side.xml")

but still with no luck, server name is empty.

Update 2:

I'm using spring-data-geode 2.0.6.RELEASE geode-core 1.2.1 My maven dependencies:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RC1</spring-cloud.version>
        <spring-cloud-services.version>1.5.0.RELEASE</spring-cloud-services.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        <dependency>
                <groupId>io.pivotal.spring.cloud</groupId>
                <artifactId>spring-cloud-services-dependencies</artifactId>
                <version>${spring-cloud-services.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

   <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-geode</artifactId>
        </dependency>

Update 3:

spring-cache-context-cluster-side.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:context="http://www.springframework.org/schema/context"
  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
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 


    <bean id="pdxSerializer" class="org.apache.geode.pdx.ReflectionBasedAutoSerializer">
        <constructor-arg value="com.WMModel.model.*"/>
    </bean>

    <util:properties id="gemfireProperties">
        <prop key="locators">${geode.cache.server.locators}</prop>
        <prop key="mcast-port">0</prop>
    </util:properties>

    <gfe:cache
        properties-ref="gemfireProperties"
        id="gemfireCache"
        use-cluster-configuration="true"
        pdx-serializer-ref="pdxSerializer" 
        copy-on-read="false" 
        critical-heap-percentage="85" 
        eviction-heap-percentage="80">
       <gfe:transaction-listener> 
            <bean class="com.WMCacheServer.db.op.WmTransactionListener"/>
        </gfe:transaction-listener>
        <gfe:transaction-writer> 
            <bean class="com.WMCacheServer.db.op.WmTransactionWriter"/>
        </gfe:transaction-writer>   
        <gfe:dynamic-region-factory/>     
    </gfe:cache>

    <!-- configure the cache and set the port to 0 for it picks the first available port -->
    <gfe:cache-server 
        id="advanced-config"
        port="${geode.cache.server.port}"
        auto-startup="true"
        cache-ref="gemfireCache" />
    <context:property-placeholder location="classpath:cache-server.properties"/>


    <gfe:partitioned-region id="Region1" copies="1">
        <gfe:eviction type="MEMORY_SIZE" threshold="512" action="LOCAL_DESTROY"/>
    </gfe:partitioned-region>
</beans>

cache-server.properties:

### For complete options list: http://gemfire.docs.gopivotal.com/index.html?q=/reference/topics/gemfire_properties.html ###

### Logging ###
log-level=config

### Turn Off Multi Cast ###
mcast-port=0

### Turn on Statistics ###
statistic-archive-file=stats.gfs
statistic-sample-rate=1000
statistic-sampling-enabled=true

enable-network-partition-detection=false

##Conserve Sockets##
conserve-sockets=false
geode.cache.server.port=40434
#geode.cache.server.locators=peer2.com[10334],localhost[10334]
geode.cache.server.locators=localhost[10334]
2
You cannot destroy Regions created in a Spring context using Gfsh. What happens when inject references to those Regions in you application, either directly or indirectly?John Blum

2 Answers

1
votes

What versions of Apache Geode and Spring Data Geode are you using?

What is the output of list members?

Judging from the CacheServerApplication class, your Spring (Data Geode) configured and bootstrapped Apache Geode server does not appear to be connecting to a/the Locator. Additionally, you can simplify the configuration to this...

@SpringBootApplication
@CacheServerApplication(name = "MyServer", locators="localhost[10334]"
    autoStartup = true, port = 41414)
@ImportResource("classpath:spring-cache-context-cluster-side.xml")
public class CacheServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheServerApplication.class, args);
    }
}

Notice that I added the name attribute to the @CacheServerApplication annotation to explicitly name the server. This is recommended since the member name must be unique in the cluster, and if you start more than 1 server using the same class, the default name (i.e. "SpringBasedCacheServerApplication") is going to conflict. Of course, it would conflict on CacheServer port number too since that is hard coded (i.e. "41414"). You can use dynamic configuration either with Configurers or Properties.

Additionally, I have set the locators attribute to "localhost[10334]". You should change the host and port of the Locator (in the "host[port]" formatted String) to the host and port on which your Locator is running/listening for member/client connections.

I have an example of a Spring configured and bootstrapped Pivotal GemFire server in my Spring Boot GemFire Server Example repo. I just upgraded this example to Spring Boot 2.0.2.RELEASE. This pulls in Spring Data Kay-SR7, which includes Spring Data GemFire 2.0.7.RELEASE, which is based on Pivotal GemFire 9.1.1.

Additionally, this example was initially based on Java config since it is employing the new Annotation-based configuration model in SDG. Therefore, there really is no point in using XML since you can define a Region in JavaConfig as well.

But, no matter. We can tweak this example slightly to be based on XML as well.

NOTE: The server in my example repo is also a self-contained, standalone server/cluster with its own Locator and Manager configuration. However, I just separated this configuration into a nested, static @Configuration class that is enabled with a Spring Profile (i.e. by setting the System property -Dspring.profiles.active=locator-manager). When this profile is enabled, you don't need a standalone Locator running, though you still can. You just have to be mindful of port conflicts, etc. Anyway...

I just added a xml-config branch to my repo.

Then, I configured the "Factorials" PARTITION Region using SDG's XML namespace, imported it, and configured the Locator endpoint to connect to externally started Locator.

Next, I ran Gfsh, started a Locator and proceeded to run the SpringBootGemFireServerExample class...

$ echo $GEMFIRE
/Users/jblum/pivdev/pivotal-gemfire-9.1.1
$ 
$ gfsh
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  / 
 / /__/ / ____/  _____/ / /    / /  
/______/_/      /______/_/    /_/    9.1.1

Monitor and Manage Pivotal GemFire

gfsh>list members
Command 'list members' was found but is not currently available (type 'help' then ENTER to learn about this command)
gfsh>
gfsh>start locator --name=LocatorOne --log-level=config --J=-Dgemfire.http-service-port=0
Starting a Geode Locator in /Users/jblum/pivdev/lab/LocatorOne...
...
Locator in /Users/jblum/pivdev/lab/LocatorOne on 10.0.0.121[10334] as LocatorOne is currently online.
Process ID: 33659
Uptime: 3 seconds
Geode Version: 9.1.1
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/LocatorOne/LocatorOne.log
JVM Arguments: -Dgemfire.log-level=config -Dgemfire.enable-cluster-configuration=true -Dgemfire.load-cluster-configuration-from-dir=false -Dgemfire.http-service-port=0 -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/pivotal-gemfire-9.1.1/lib/geode-core-9.1.1.jar:/Users/jblum/pivdev/pivotal-gemfire-9.1.1/lib/geode-dependencies.jar

Successfully connected to: JMX Manager [host=10.0.0.121, port=1099]

Cluster configuration service is up and running.


gfsh>list members
   Name    | Id
---------- | -------------------------------------------------
LocatorOne | 10.0.0.121(LocatorOne:33659:locator)<ec><v0>:1024

Now, I proceed in starting my SpringBootGemFireServerExample class from within my IDE. Keep in mind, I have not enabled the "locator-manager" Spring profile (i.e. -Dspring.profiles.active= (empty)). I don't want to start an embedded Locator/Manager since I want to connect to the Gfsh started Locator, hence this...

@CacheServerApplication(... locators="localhost[10334]")

After I run my server from my IDE, connecting to this Locator...

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.2.RELEASE)

[info 2018/05/11 11:53:36.883 PDT <main> tid=0x1] 
---------------------------------------------------------------------------

  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with this
  work for additional information regarding copyright ownership.

  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
  License for the specific language governing permissions and limitations
  under the License.

---------------------------------------------------------------------------
Build-Date: 2017-09-08 19:39:04 +0000
Build-Id: root 51
Build-Java-Version: 1.8.0_144
Build-Platform: Linux 4.4.0-62-generic amd64
GemFire-Source-Date: 2017-09-01 21:01:32 +0000
GemFire-Source-Repository: support/9.1
GemFire-Source-Revision: ac20a06062204a8f6ba2acaaf2c7dbc1a3d0cfe0
Product-Name: Pivotal GemFire
Product-Version: 9.1.1
Source-Date: 2017-09-08 19:07:34 +0000
Source-Repository: support/9.1
Source-Revision: e756828d0e631cec47f3d027555c022f0fb0e5cc
Native version: native code unavailable
Running on: /10.0.0.121, 8 cpu(s), x86_64 Mac OS X 10.10.5 
Communications version: 65
Process ID: 33670
...
..
.
[info 2018/05/11 11:53:38.454 PDT <main> tid=0x1] CacheServer Configuration:   port=40404 max-connections=800 max-threads=0 notify-by-subscription=true socket-buffer-size=32768 maximum-time-between-pings=60000 maximum-message-count=230000 message-time-to-live=180 eviction-policy=none capacity=1 overflow directory=. groups=[] loadProbe=ConnectionCountProbe loadPollInterval=5000 tcpNoDelay=true

I can see that the server joined the cluster defined by the Locator in Gfsh...

gfsh>list members
         Name           | Id
----------------------- | --------------------------------------------------
LocatorOne              | 10.0.0.121(LocatorOne:33659:locator)<ec><v0>:1024
SpringBootGemFireServer | 10.0.0.121(SpringBootGemFireServer:33670)<v1>:1025

gfsh>describe member --name=SpringBootGemFireServer
Name        : SpringBootGemFireServer
Id          : 10.0.0.121(SpringBootGemFireServer:33670)<v1>:1025
Host        : 10.0.0.121
Regions     : Factorials
PID         : 33670
Groups      : 
Used Heap   : 52M
Max Heap    : 3641M
Working Dir : /Users/jblum/pivdev/spring-data-examples-workspace/spring-boot-gemfire-server-example/build
Log file    : /Users/jblum/pivdev/spring-data-examples-workspace/spring-boot-gemfire-server-example/build
Locators    : localhost[10334]

Cache Server Information
Server Bind              : 
Server Port              : 40404
Running                  : true
Client Connections       : 0

You can also see the "Factorials" PARTITION Region is hosted by the "SpringBootGemFireServer", which is also evident from...

gfsh>list regions
List of regions
---------------
Factorials

gfsh>describe region --name

required --name: Name/Path of the region to be described.; no default value
gfsh>describe region --name=/Factorials
..........................................................
Name            : Factorials
Data Policy     : partition
Hosting Members : SpringBootGemFireServer

Non-Default Attributes Shared By Hosting Members  

 Type  |    Name     | Value
------ | ----------- | ---------
Region | size        | 0
       | data-policy | PARTITION

Next, I access a value with a numeric key.

NOTE: This example attaches a "Factorial" computational based CacheLoader to the "Factorials" PARTITION Region.

gfsh>get --region=/Factorials --key=3 --key-class=java.lang.Long
Result      : true
Key Class   : java.lang.Long
Key         : 3
Value Class : java.lang.Long
Value       : 6


gfsh>get --region=/Factorials --key=5 --key-class=java.lang.Long
Result      : true
Key Class   : java.lang.Long
Key         : 5
Value Class : java.lang.Long
Value       : 120

And finally, I can query the values in the "Factorials" PARTITION Region, like so...

gfsh>query --query="SELECT * FROM /Factorials"
Result : true
Limit  : 100
Rows   : 2

Result
------
6
120

When you "describe" the Region, you can see that it has been changed (see "size").

gfsh>describe region --name=/Factorials
..........................................................
Name            : Factorials
Data Policy     : partition
Hosting Members : SpringBootGemFireServer

Non-Default Attributes Shared By Hosting Members  

 Type  |    Name     | Value
------ | ----------- | ---------
Region | size        | 2
       | data-policy | PARTITION

Anyway, all is well. Hope this helps!

-John

0
votes

OK, solved by changing Maven dependencies. Thanks John! Looks like there is conflict between spring-boot and spring-data-geode. Hope that geode-spring-boot-starter will be released soon. My updated dependency:

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-geode</artifactId>
        <version>2.0.1.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>          
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.7</version>
    </dependency>

    <dependency>
      <groupId>org.springframework.shell</groupId>
      <artifactId>spring-shell</artifactId>
      <version>1.2.0.RELEASE</version>
       <exclusions>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
        </exclusion>
      </exclusions>
    </dependency>