Access Keys:
Skip to content (Access Key - 0)

GemFire Versions

About GemFire Enterprise 6.5

Getting Started

Documentation

Resources

Articles

Developer Notes

Tools & Libraries

Toggle Sidebar

Integrating GemFire with the Spring IoC Container

Introduction

Spring and the Inversion of Control module

Spring is a popular open source application framework for the Java platform. It consists of many modules that facilitate such varied tasks as transaction management, aspect-oriented programming, MVC for the Web, and dependency injection. This article focuses specifically on the Spring IoC module and how GemFire can be seamlessly wired into a Spring IoC application.

Spring IoC is a Spring module that implements the Inversion of Control pattern using dependency injection. Dependency injection is in a sense an alternative to the service locator pattern. See here for a detailed discussion of this topic.

Intended audience

This article assumes a basic working knowledge of the Spring IoC and dependency injection concepts. Please follow the above links for details about Spring IoC and dependency injection.

A simple example: the Phonebook application

The purpose of this example is to demonstrate how GemFire can be seamlessly wired into a Spring application, without making any coding changes. First we will take a simple spring application that retrieves a Phonebook bean from the spring ApplicationContext and uses it to store and retrieve phone numbers. The phonebook bean uses a map to store the phone numbers by name. Then we will show how easily we can introduce GemFire distributed system to this spring application by adding couple of GemFire related beans to the spring configuration. Without making any coding changes and making any explicit GemFire API calls, we have added a highly available and scalable distributed system to our phone book spring application. This was possible because a data region is similar to a Map that stores data in a key value pair. The API of a data region is similar to a Map where data can be retrieved and stored using get() and put() methods respectively. But as mentioned below to take advantage of the many advanced features of GemFire, programming directly to the GemFire API may be required.

Here's the Phonebook class:

Phonebook.java
package com.spring.example;

import java.util.Map;

public class Phonebook {

    private final Map<String, String> phoneNumbersByName;

    public Phonebook(Map<String, String> phoneNumbersByName) {
    	this.phoneNumbersByName = phoneNumbersByName;
    }

    public String getPhoneNumber(String name) {
        return phoneNumbersByName.get(name);
    }

    public void setPhoneNumber(String name, String phoneNumber) {
        phoneNumbersByName.put(name, phoneNumber);
    }

}

And here's a Spring beans XML file that creates a Phonebook instance:

phonebook-beans-no-gemfire.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="inMemoryPhonebookMap" class="java.util.HashMap" />

  <bean id="phonebook" class="com.spring.example.Phonebook">
    <constructor-arg index="0" ref="inMemoryPhonebookMap" />
  </bean>

</beans>

And here's a simple application that retrieves the Phonebook bean from the Spring ApplicationContext and uses it to store and retrieve phone numbers.

PhonebookMain.java
package com.spring.example;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PhonebookMain {

    public static void main(String[] args) {

        // Make sure that the Spring xml config file is passed as an argument. Otherwise exit with a proper message
        if (args.length < 1) {
            System.out.println("Usage: PhonebookMain xmlConfigFile");
                System.exit(1);
            }

        String config_xml = args[0];

        // Parse the Spring beans XML file; resolve, instantiate, and wire up our Phonebook application.
        ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(config_xml);

        Phonebook phonebook = (Phonebook) appCtx.getBean("phonebook");

        String phoneNumber = phonebook.getPhoneNumber("Fred");
        System.out.println("Current phone number for Fred: " + phoneNumber);

        String newPhoneNumber = phoneNumber == null ? "5551212" : String.valueOf(Integer.parseInt(phoneNumber) + 1);
        System.out.println("Setting phone number for fred to " + newPhoneNumber);
        phonebook.setPhoneNumber("Fred", newPhoneNumber);
    }
}
Integrating GemFire into the Phonebook app

Let's modify our Phonebook app to be backed by a GemFire Enterprise distributed system. By adding a little GemFire configuration and a couple of new Spring beans, our application's data will be backed by a scalable, fault-tolerant, highly available distributed system without changing any Java code. Since our phonebook is stored in the data fabric, all instances of our application will share the same phonebook data.

Configuring GemFire

First, we'll need to create the two GemFire configuration files: gemfire.properties, which defines global GemFire properties, and cache.xml, which defines the distributed data structures that will be used by this GemFire-enabled application.

gemfire.properties
\# gemfire.properties file for the Phonebook application
mcast-port=41112
cache-xml-file=cache.xml
name=Gemfire_Spring_Integration

A GemFire cache configuration file can be as below:

cache.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 6.0//EN"
    "http://www.gemstone.com/dtd/cache6_0.dtd">
<cache>
  <region name="phoneBookRegion">
    <region-attributes scope="distributed-ack" data-policy="replicate" />
  </region>
</cache>

Creating GemFire beans and wiring them into the Phonebook app

We'll modify our Spring beans XML file to instantiate the core GemFire objects – DistributedSystem and Cache. From our Cache bean, we can retrieve any Region beans that our application needs.

Since Region implements the Map interface, we can simply inject our phonebookRegion in place of the HashMap used in the original Spring configuration.

Of course, GemFire provides many advanced features outside the scope of this example, some of which require programming directly to the GemFire API. In those cases, we would simply write our classes to expect Cache or Region objects instead of a plain Map.

phonebook-beans-with-gemfire.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:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">


  <!--
    | When this bean is instantiated, this peer will connect to the GemFire distributed system.
   -->
  <bean
        id="distributedSystem"
        class="com.gemstone.gemfire.distributed.DistributedSystem"
        factory-method="connect">
    <constructor-arg index="0">
      <util:properties id="distributedSystemProperties" location="gemfire.properties" />
    </constructor-arg>
  </bean>

  <!--
    | When this bean is instantiated, GemFire will parse our cache.xml file and
    | initialize the distributed data structures we've defined there. At this point,
    | the GemFire initialization process is complete.
   -->
  <bean id="cache" class="com.gemstone.gemfire.cache.CacheFactory" factory-method="create">
    <constructor-arg index="0" ref="distributedSystem"/>
  </bean>

  <bean id="attributesFactory" class="com.gemstone.gemfire.cache.AttributesFactory" />

  <!--
    | Now that GemFire is initialized, we can retrieve the Region that backs
    | our Phonebook class.
   -->
  	<bean id="phonebookRegion" factory-bean="cache" factory-method="getRegion">
  		<constructor-arg index="0" value="phonebookRegion" />
	</bean>

  <bean id="phonebook" class="com.spring.example.Phonebook">
    <constructor-arg index="0" ref="phonebookRegion" />
  </bean>

</beans>
Running the example
  • Create a directory in which you would like to run the example
  • Expand the Spring_Gemfire.zip into your chosen directory
  • Follow the Readme.txt for detailed instructions.

Child Pages

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
Adaptavist Theme Builder (3.4.0-M2-conf210) Powered by Atlassian Confluence 2.10.3, the Enterprise Wiki.