In my previous tutorial, I have explained about the accessing data using Spring Data GemFire. GemFire is the in-memory data system used in the distributed environments. The performance and scalability achieved by GemFire by using the efficient caching techniques for storing in the in-memory. In this tutorial I will explain the purpose, in that connections will be made for http://themoneyconverter.com/ for transferring RSS Feed for different counties. After that the elapsed time should be computed by subtract of the end time from the start time.
Also read:
1. Business Scenario
To ensure that the Spring GemFire framework does provide a proper solution for the Cache, we created a MoneyRSS spring bean that contains a loadRss service that accept a country as an enum value. After that an HTTP connection got opened for reading the rss for the provided country. The implementation of the whole bean is provided below:
MoneyRSS.java
package net.javabeat.springdata.data; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @Component public class MoneyRSS { @Cacheable("moneyRss") public Object loadRss(Country country){ try { URL url = new URL("http://themoneyconverter.com/rss-feed/"+country.code+"/rss.xml"); try { return url.openConnection().getContent(); } catch (IOException e) { e.printStackTrace(); } } catch (MalformedURLException e) { e.printStackTrace(); } return null; } public static enum Country { INDIA("INDIA","INR"), UK("United Kingdom","GBP"), USA("United States","USD"); Country(String name, String code){ this.code = code; } private String code; private String name; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } } }
2. Spring Bean Configurations
It’s the spring container configuration file that used for defining spring beans, repositories if there is one, GemFire cache, Regions, cache managers and etc.
SpringContext.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:context="http://www.springframework.org/schema/context" xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire" xmlns:gfe="http://www.springframework.org/schema/gemfire" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd"> <!-- Search for spring components --> <context:component-scan base-package="net.javabeat"></context:component-scan> <!-- Declare GemFire Cache --> <gfe:cache/> <!-- Local region for being used by the Message --> <gfe:local-region id="moneyRss"/> <!-- It's mandatory for enabling the Cache --> <bean id="cacheManager" class="org.springframework.data.gemfire.support.GemfireCacheManager" p:cache-ref="gemfireCache"/> <!-- Dummy Bean for EnableCaching --> <bean id="enableCachingBean" class="net.javabeat.springdata.executable.Executable"></bean> </beans>
3. Maven Build File
It’s the maven build file that contains the required libraries for getting the example up and running.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.javabeat.springdata</groupId> <artifactId>SpringData-GemFire-Cache</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>Spring Data</name> <!-- Just for including the Spring framework necessary libraries inone shot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.0.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-gemfire</artifactId> <version>1.3.4.RELEASE</version> </dependency> <dependency> <groupId>com.gemstone.gemfire</groupId> <artifactId>gemfire</artifactId> <version>7.0.1</version> </dependency> <!-- Google List API --> <dependency> <groupId>com.google.collections</groupId> <artifactId>google-collections</artifactId> <version>1.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>http://repo.spring.io/libs-snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>gemstone</id> <url>http://dist.gemstone.com.s3.amazonaws.com/maven/release/</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>http://repo.spring.io/libs-snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>
4. Spring Data GemFire Example Application
It’s the Spring Data GemFire Sample Application that will be used for starting up the Spring framework and for initiating an rss HTTP request through using of GemFireBean.
Executable.java
package net.javabeat.springdata.executable; import net.javabeat.springdata.bean.GemFireBean; import net.javabeat.springdata.data.MoneyRSS; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; @EnableCaching public class Executable { // Getting spring context public static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new ClassPathResource("SpringContext.xml").getPath()); // GemFireBean declaration, it's just a normal spring bean public static GemFireBean gfb; public static void main(String[] args) { // Acquiring the GemFireBean gfb = (GemFireBean)context.getBean("gemFireBean"); loadAndTimeIt(1,gfb,MoneyRSS.Country.INDIA); loadAndTimeIt(2,gfb,MoneyRSS.Country.INDIA); loadAndTimeIt(3,gfb,MoneyRSS.Country.INDIA); loadAndTimeIt(1,gfb,MoneyRSS.Country.USA); loadAndTimeIt(2,gfb,MoneyRSS.Country.USA); loadAndTimeIt(3,gfb,MoneyRSS.Country.USA); loadAndTimeIt(1,gfb,MoneyRSS.Country.UK); loadAndTimeIt(2,gfb,MoneyRSS.Country.UK); loadAndTimeIt(3,gfb,MoneyRSS.Country.UK); } private static void loadAndTimeIt(int tryIndex,GemFireBean bean,MoneyRSS.Country country){ // Start Time long start = System.currentTimeMillis(); // Load document Object o = gfb.getMoneyRss().loadRss(country); // End Time Computation long elapsed = System.currentTimeMillis() - start; // Print out the time message System.out.println("Try # :: "+tryIndex+" :: For :: "+country+" :: Found " + o + ", and it only took " + elapsed + " ms to find out!\n"); } }
5. GemFire Cache Demo
It’s the demonstration of using GemFire for caching the request. This output shows the how much time taken for each request. If you look at it closely, for the first look up of the data, it took longer time, but later requests it is much faster. It shows that if you have a performance issues for fetching the data, GemFire could be good option to try out.
[info 2014/05/24 01:00:24.765 EEST <main> tid=0x1] Defaulting license-working-dir to current working directory "D:\Krishna\EclipseLink\Workspace\SpringData-GemFire-Cache". [info 2014/05/24 01:00:24.775 EEST <main> tid=0x1] Acquiring default evaluation license. [info 2014/05/24 01:00:26.554 EEST <main> tid=0x1] vFabric Licensing Client activation of license required 1778 milliseconds. [info 2014/05/24 01:00:26.618 EEST <main> tid=0x1] Using the default evaluation license. [info 2014/05/24 01:00:26.619 EEST <main> tid=0x1] Licensing required 1856 milliseconds. [info 2014/05/24 01:00:26.758 EEST <main> tid=0x1] GemFire P2P Listener started on tcp:///192.168.1.100:59267 [info 2014/05/24 01:00:30.966 EEST <main> tid=0x1] Membership: lead member is now mohammad-amr-lt:49779 [config 2014/05/24 01:00:30.974 EEST <main> tid=0x1] This member, mohammad-amr-lt:49779, is becoming group coordinator. [info 2014/05/24 01:00:31.011 EEST <main> tid=0x1] Entered into membership in group GF70 with ID mohammad-amr-lt:49779. [info 2014/05/24 01:00:31.013 EEST <main> tid=0x1] Starting DistributionManager mohammad-amr-lt:49779. [info 2014/05/24 01:00:31.014 EEST <main> tid=0x1] Initial (membershipManager) view = [mohammad-amr-lt:49779{lead}] [info 2014/05/24 01:00:31.015 EEST <main> tid=0x1] Admitting member <mohammad-amr-lt:49779>. Now there are 1 non-admin member(s). [info 2014/05/24 01:00:31.015 EEST <main> tid=0x1] mohammad-amr-lt:49779 is the elder and the only member. [info 2014/05/24 01:00:31.130 EEST <main> tid=0x1] Did not hear back from any other system. I am the first one. [info 2014/05/24 01:00:31.130 EEST <main> tid=0x1] DistributionManager mohammad-amr-lt:49779 started on 239.192.81.1[10334]. There were 0 other DMs. others: [] [info 2014/05/24 01:00:31.153 EEST <Thread-3 StatSampler> tid=0x21] Disabling statistic archival. [info 2014/05/24 01:00:31.394 EEST <main> tid=0x1] Initializing region _monitoringRegion_mohammad-amr-lt49779 [config 2014/05/24 01:00:31.422 EEST <main> tid=0x1] Command Service could not be initialized. Could not find Spring Shell library which is needed for CLI/gfsh in classpath. Internal support for CLI & gfsh is not enabled. [info 2014/05/24 01:00:31.477 EEST <main> tid=0x1] Initializing region PdxTypes Try # :: 1 :: For :: INDIA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@629a99eb, and it only took 741 ms to find out! Try # :: 2 :: For :: INDIA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@629a99eb, and it only took 3 ms to find out! Try # :: 3 :: For :: INDIA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@629a99eb, and it only took 0 ms to find out! Try # :: 1 :: For :: USA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@2af4ca49, and it only took 685 ms to find out! Try # :: 2 :: For :: USA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@2af4ca49, and it only took 1 ms to find out! Try # :: 3 :: For :: USA :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@2af4ca49, and it only took 0 ms to find out! Try # :: 1 :: For :: UK :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@64ad97f5, and it only took 599 ms to find out! Try # :: 2 :: For :: UK :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@64ad97f5, and it only took 1 ms to find out! Try # :: 3 :: For :: UK :: Found sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@64ad97f5, and it only took 0 ms to find out! [info 2014/05/24 01:00:33.729 EEST <Distributed system shutdown hook> tid=0xa] VM is exiting - shutting down distributed system
6. Summary
You’ve just developed an application that uses the GemFire cache feature. The example provided here makes multiple requests for getting the RSS money feeds for different countries, where the first request for every single country took long time in comparison of those second and third.