Search This Blog

Wednesday, 20 February 2013

MyBatis-Spring with vFabric SQLFire

MyBatis-Spring helps you integrate your MyBatis code seamlessly with Spring. Using the classes in this library, Spring will load the necessary MyBatis factory and session classes for you. This library also provides an easy way to inject MyBatis data mappers into your service beans. Finally, MyBatis-Spring will handle transactions and translate MyBatis exceptions into Spring DataAccessExceptions.

Here is a simple exampled based on the classic DEPT table.

1. We are working with a DEPT table in SQLFire defined as follows.

DEPT table
  
sqlf> describe dept;
COLUMN_NAME         |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
DEPTNO              |INTEGER  |0   |10  |10    |NULL      |NULL      |NO      
DNAME               |VARCHAR  |NULL|NULL|14    |NULL      |28        |YES     
LOC                 |VARCHAR  |NULL|NULL|13    |NULL      |26        |YES     

3 rows selected

2. Setup your pom.xml to include the following.

pom.xml
  
<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>sqlfire-mybatis</groupId>
  <artifactId>sqlfire-mybatis</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>sqlfire-mybatis</name>
  <properties>
    <spring.version>3.1.2.RELEASE</spring.version>
    <mybatis.version>3.1.1</mybatis.version>
    <mybatis.spring.version>1.1.1</mybatis.spring.version>
    <dbcp.version>1.4</dbcp.version>
    <cglib.version>2.2.2</cglib.version>
  </properties>
  <dependencies>
 <dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>${mybatis.version}</version>
 </dependency>
 <dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis-spring</artifactId>
   <version>${mybatis.spring.version}</version>
 </dependency>
 <dependency>
   <groupId>commons-dbcp</groupId>
   <artifactId>commons-dbcp</artifactId>
   <version>${dbcp.version}</version>
 </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
 <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>${cglib.version}</version>
 </dependency>
  </dependencies>
  <repositories>
 <repository>
     <id>mybatis-snapshot</id>
     <name>MyBatis Snapshot Repository</name>
     <url>https://oss.sonatype.org/content/repositories/snapshots</url>
 </repository>
  </repositories>
</project>

3. Create the domain modelclass Dept.java, with the standard getter/setters for each attribute. Omitting the full class here.

Dept.java
  
package pas.au.vmware.se.mybatis.domain;

public class Dept 
{
 private int deptno;
 private String dname;
 private String loc;
 
 public Dept()
 {
  
 }
 
 public Dept(int deptno, String dname, String loc) 
 {
  super();
  this.deptno = deptno;
  this.dname = dname;
  this.loc = loc;
 }

......
 

4.Create a DeptMapper.xml file. I prefer to keep SQL out of the java class wheever I can , hence avoided using annotations here.

DeptMapper.xml
  
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="pas.au.vmware.se.mybatis.mapper.DeptMapper">
 
    <resultMap id="result" type="pas.au.vmware.se.mybatis.domain.Dept">
        <result property="deptno" column="DEPTNO"/>
        <result property="dname" column="DNAME"/>
        <result property="loc" column="LOC"/>
    </resultMap>
 
    <select id="getAll" resultMap="result">
        SELECT * FROM DEPT
    </select>

 <select id="getById" parameterType="int" resultMap="result">
  SELECT * FROM DEPT WHERE DEPTNO = #{deptno}
 </select>
    
    <insert id="insertDept" parameterType="pas.au.vmware.se.mybatis.domain.Dept">
        INSERT INTO dept (deptno, dname, loc)
        VALUES (#{deptno}, #{dname}, #{loc})
    </insert>
</mapper>

5. Create a DeptMapper interface file. Notice how this is a clean interface and no annotations to specify the SQL we are using as that's in the DeptMapper.xml file above.

DeptMapper.java
  
package pas.au.vmware.se.mybatis.mapper;

import java.util.List;

import pas.au.vmware.se.mybatis.domain.Dept;

public interface DeptMapper 
{
  public List<Dept> getAll();
  public Dept getById (int deptno);
  public void insertDept (Dept dept);
}

6. Create a service class for the DEPT table as shown below.

DeptService.java
  
package pas.au.vmware.se.mybatis.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pas.au.vmware.se.mybatis.domain.Dept;
import pas.au.vmware.se.mybatis.mapper.DeptMapper;

@Service("deptService")
public class DeptService 
{

 @Autowired
 private DeptMapper deptMapper;

 public DeptMapper getDeptMapper() {
  return deptMapper;
 }

 public void setDeptMapper(DeptMapper deptMapper) {
  this.deptMapper = deptMapper;
 }
 
 public List<Dept> getAll()
 {
  return getDeptMapper().getAll();
 }
 
 public Dept getById(int deptno)
 {
  return getDeptMapper().getById(deptno);
 }
 
 @Transactional
 public void insertDept (Dept dept)
 {
  getDeptMapper().insertDept(dept);
 }
}  

7. Create a spring application context file as shown below.

application-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:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
     <property name="driverClassName" value="com.vmware.sqlfire.jdbc.ClientDriver" />
     <property name="url" value="jdbc:sqlfire://localhost:1527/" />
     <property name="username" value="app" />
     <property name="password" value="app" />
 </bean>

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
 </bean>

   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
   </bean>
  
    <tx:annotation-driven />

 <context:component-scan base-package="pas.au.vmware.se.mybatis.service" />

   <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="pas.au.vmware.se.mybatis.mapper" />
   </bean>
      
</beans> 

8. Finally create a test class to verify the setup as shown below.

SpringDeptTest.java
  
package pas.au.vmware.se.mybatis.test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import pas.au.vmware.se.mybatis.domain.Dept;
import pas.au.vmware.se.mybatis.service.DeptService;

public class SpringDeptTest 
{

 /**
  * @param args
  */
 public static void main(String[] args) 
 {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "application-context.xml");
        
        DeptService deptService = (DeptService) context.getBean("deptService");
        
        Dept dept = new Dept(99, "MYBATIS-TEST", "BUNDOORA");
        deptService.insertDept(dept);
        System.out.println("New DEPT added to SQLFire\n");
          
        List<Dept> deps = deptService.getAll();
        
        for (Dept d: deps)
        {
         System.out.println(d);
        }
        
        System.out.println("\n" + deptService.getById(20));
        
 }

}

9. Run SpringDeptTest.java and verfy output as shown below.

Feb 20, 2013 9:14:39 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1fff7a1e: startup date [Wed Feb 20 21:14:39 EST 2013]; root of context hierarchy
Feb 20, 2013 9:14:39 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [application-context.xml]
Feb 20, 2013 9:14:40 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@57ac3379: defining beans [dataSource,sqlSessionFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,deptService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.mybatis.spring.mapper.MapperScannerConfigurer#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,deptMapper]; root of factory hierarchy
New DEPT added to SQLFire

Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]
Dept [deptno=20, dname=RESEARCH, loc=DALLAS]
Dept [deptno=30, dname=SALES, loc=CHICAGO]
Dept [deptno=40, dname=OPERATIONS, loc=BRISBANE]
Dept [deptno=50, dname=MARKETING, loc=ADELAIDE]
Dept [deptno=60, dname=DEV, loc=PERTH]
Dept [deptno=70, dname=SUPPORT, loc=SYDNEY]
Dept [deptno=99, dname=MYBATIS-TEST, loc=BUNDOORA]

Dept [deptno=20, dname=RESEARCH, loc=DALLAS]


The full project structure is as follows showing where the XML files exists in this setup.


Wednesday, 13 February 2013

Adding JSON Documents into GemFire Cache

The JSONFormatter API allows you to put JSON formatted documents into regions and retrieve them later by storing the documents internally as PdxInstances. vFabric GemFire now supports the use of JSON formatted documents natively. When you add a JSON document to a GemFire cache, you call the JSONFormatter APIs to transform them into the PDX format (as a PdxInstance), which enables GemFire to understand the JSON document at a field level.
 
In terms of querying and indexing, because the documents are stored internally as PDX, applications can index on any field contained inside the JSON document including any nested field (within JSON objects or JSON arrays.) Any queries run on these stored documents will return PdxInstances as results. To update a JSON document stored in GemFire, you can execute a function on the PdxInstance.

You can then use the JSONFormatter to convert the PdxInstance results back into the JSON document.

Here is a simple example.

1. server side cache.xml file, in this demo we just start up one cache server

cache.xml
  
<?xml version="1.0"?>
<!DOCTYPE cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<cache>
    <cache-server port="40404"/>
    <region name="jsonregion">
       <region-attributes refid="REPLICATE" />
    </region>
</cache>

2. Client side cache.xml

client.xml
  
<?xml version="1.0"?>
<!DOCTYPE client-cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<!--
  | Client.xml
  |
  | Configures a region as a client region in a client/server cache. The 
  | region's pool connects to a cacheserver listening on port 40404.
 -->
<client-cache>
  <pool name="client" subscription-enabled="true">
    <server host="localhost" port="40404" />
  </pool>

  <region name="jsonregion">
    <region-attributes refid="PROXY">      
    </region-attributes>
  </region>
</client-cache>  

3. Java class to insert some JSON formatted documents into the cache then how to query them back using a field from the JSON document itself.

JSONGemFireClient.java
  
package vmware.au.gemfire7.json.client;

import java.util.List;

import org.json.simple.JSONObject;

import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.pdx.JSONFormatter;
import com.gemstone.gemfire.pdx.PdxInstance;

public class JSONGemFireClient 
{

   public static final String REGION_NAME = "jsonregion";
   public ClientCache cache = null;
   
   public JSONGemFireClient()
   {
    cache = new ClientCacheFactory()
          .set("name", "JSONClient")
          .set("cache-xml-file", "xml/client.xml")
          .create();   
   }
 
   @SuppressWarnings("unchecked")
   public void run() throws Exception
   {
    JSONObject obj = null;
    
    System.out.println("Connecting to the distributed system and creating the cache.");
      
    // Get the exampleRegion
    Region<String, PdxInstance> jsonregion = cache.getRegion(REGION_NAME);
    System.out.println("Example region \"" + jsonregion.getFullPath() + "\" created in cache.");
    
    // add 5 entries with age = 30
     
    for (int i = 1; i <= 5; i++)
    {
      obj = new JSONObject();
      
      obj.put("name", String.format("Person%s", i));
      obj.put("age", 30);
     
      jsonregion.put(String.valueOf(i), JSONFormatter.fromJSON(obj.toJSONString()));
    }
      
    // add 5 entries with age = 20
    for (int i = 6; i <= 10; i++)
    {
      obj = new JSONObject();
      
      obj.put("name", String.format("Person%s", i));
      obj.put("age", 20);
     
      jsonregion.put(String.valueOf(i), JSONFormatter.fromJSON(obj.toJSONString()));
    }
    
    // Query region
    SelectResults<PdxInstance> sr = jsonregion.query("age = 30");
    
    System.out.println("Number of entries where age = 30 is -> " + sr.size());
    
    List<PdxInstance> entries = sr.asList();
    for (PdxInstance val: entries)
    {
     System.out.println("\n** JSON data ** ");
     System.out.println("Name = " + val.getField("name"));
     System.out.println("Full JSON data -> \n" + JSONFormatter.toJSON(val));
    }
    
    cache.close();
   }
 
   /**
    * @param args
    */
   public static void main(String[] args) 
   {
    // TODO Auto-generated method stub
    JSONGemFireClient test = new JSONGemFireClient();
    
    try 
    {
   test.run();
    } 
    catch (Exception e) 
    {
   // TODO Auto-generated catch block
   e.printStackTrace();
    }
   }

}

4. Run the java class above and verify output as follows

....
[info 2013/02/13 09:41:15.464 EST
tid=0x1] Defining: PdxType[
      id=1, name=__GEMFIRE_JSON, fields=[
          age:byte:0:idx0(relativeOffset)=0:idx1(vlfOffsetIndex)=0
          name:String:1:idx0(relativeOffset)=1:idx1(vlfOffsetIndex)=-1]]
Number of entries where age = 30 is -> 5

** JSON data **
Name = Person1
Full JSON data ->
{
  "age" : 30,
  "name" : "Person1"
}

** JSON data **
Name = Person4
Full JSON data ->
{
  "age" : 30,
  "name" : "Person4"
}

** JSON data **
Name = Person2
Full JSON data ->
{
  "age" : 30,
  "name" : "Person2"
}

** JSON data **
Name = Person5
Full JSON data ->
{
  "age" : 30,
  "name" : "Person5"
}

** JSON data **
Name = Person3
Full JSON data ->
{
  "age" : 30,
  "name" : "Person3"
}
....



5. Finally use GFSH to query the region itself and you wouldn't even know your using JSON stored documents and would rely on using JSONFormatter  to convert the data back into JSON document.
  
gfsh>connect --jmx-manager=localhost[1099]
Connecting to Manager at [host=localhost, port=1099] ..
Successfully connected to: [host=localhost, port=1099]

gfsh>list regions;
List of regions
---------------
jsonregion

gfsh>query --query="select * from /jsonregion";

Result     : true
startCount : 0
endCount   : 20
Rows       : 10

age | name
--- | --------
30  | Person1
30  | Person4
20  | Person8
20  | Person10
20  | Person6
30  | Person2
30  | Person5
20  | Person9
20  | Person7
30  | Person3

NEXT_STEP_NAME : END 

More information can be found on the link below.

http://pubs.vmware.com/vfabricNoSuite/index.jsp?topic=/com.vmware.vfabric.gemfire.7.0/developing/data_serialization/jsonformatter_pdxinstances.html

Monday, 11 February 2013

JSON messages with RabbitMQ

Using JSON message solution in RabbitMQ gives you something that's a bit more friendly in polyglot systems, and leaves your application with more future flexibility. Although we can use Java Objects this puts restrictions on the the recipients of your message as they're also going to need to be in Java. JSON (JavaScript Object Notation) is rather common alternative that is more flexible and portable across different languages and platforms.

In the example below we use the following

RabbitMQ 3.0 - http://www.rabbitmq.com/
JSON-Simple - http://code.google.com/p/json-simple/

1. Create a start up script to start a single RabbitMQ server.

export RABBITMQ_NODE_PORT=5676
export RABBITMQ_NODENAME=rabbit_standalone

export RABBIT_HOME=/Users/papicella/vmware/software/rabittMQ/rabbitmq_server-3.0.0

$RABBIT_HOME/sbin/rabbitmq-server -detached

netstat -an | grep 5676


2. Start as shown below.

[Mon Feb 11 21:07:17 papicella@:~/rabbitMQ/standalone-rabbit ] $ sudo ./node1.sh
Warning: PID file not written; -detached was passed.

tcp4       0      0  *.5676                 *.*                    LISTEN    
tcp46      0      0  *.5676                 *.*                    LISTEN   
 

3. Create a RECEIVE client which will create a QUEUE and wait for messages. IT is expecting a JSON string to be sent.

JSONRecv.java
  
package pas.au.rabbitmq30.tutorial.helloworld.json;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

public class JSONRecv 
{
 private final static String QUEUE_NAME = "json-example";
 private ConnectionFactory factory = null;
 private JSONParser parser;
 
 public JSONRecv() 
 {
  parser = new JSONParser();
 }

 public void run () throws Exception
 {
  factory = new ConnectionFactory();
     factory.setHost("localhost");
     factory.setPort(5676);
     Connection connection = factory.newConnection();
     Channel channel = connection.createChannel();

     channel.queueDeclare(QUEUE_NAME, false, false, false, null);
     System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
     
     QueueingConsumer consumer = new QueueingConsumer(channel);
     channel.basicConsume(QUEUE_NAME, true, consumer);
     
     while (true) 
     {
       QueueingConsumer.Delivery delivery = consumer.nextDelivery();
       String message = new String(delivery.getBody()); 
       JSONObject obj = (JSONObject) parser.parse(message);
       
       System.out.println(" [x] Received '" + obj.toJSONString() + "'");
     }  
 }
 
 /**
  * @param args
  * @throws Exception 
  */
 public static void main(String[] args) throws Exception 
 {
  // TODO Auto-generated method stub
  JSONRecv test = new JSONRecv();
  test.run();
 }

}  

4. Create a SEND client and place 10 JSON objects onto the QUEUE

JSONSend.java
  
package pas.au.rabbitmq30.tutorial.helloworld.json;

import org.json.simple.JSONObject;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class JSONSend 
{
 private final static String QUEUE_NAME = "json-example";
 private ConnectionFactory factory = null;
 
 public JSONSend() 
 {
  // TODO Auto-generated constructor stub
 }
 
 @SuppressWarnings("unchecked")
 public void run() throws Exception
 {
     factory = new ConnectionFactory(); 
     factory.setHost("localhost"); 
     factory.setPort(5676);
     
     System.out.println("connected to rabbitMQ on localhost ...");
     Connection connection = factory.newConnection();
     Channel channel = connection.createChannel();

     channel.queueDeclare(QUEUE_NAME, false, false, false, null);
     for (int i = 1; i <= 10; i++)
     {
      JSONObject obj = new JSONObject();
      
      obj.put("name", String.format("Person%s", i));
      obj.put("age", new Integer(37));
     
      channel.basicPublish("", QUEUE_NAME, null, obj.toJSONString().getBytes()); 
      System.out.println(" [x] Sent '" + obj.toJSONString() + "'");
     }
     
     channel.close();
     connection.close();
 }
 
 /**
  * @param args
  * @throws Exception 
  */
 public static void main(String[] args) throws Exception 
 {
  // TODO Auto-generated method stub
  JSONSend test = new JSONSend();
  test.run();
 }

}

5. Run JSONRecv.java and verify output as follows

[*] Waiting for messages. To exit press CTRL+C

6. Run JSONSend.java and then check the output from JSONRecv.java.

 [*] Waiting for messages. To exit press CTRL+C
 [x] Received '{"name":"Person1","age":37}'
 [x] Received '{"name":"Person2","age":37}'
 [x] Received '{"name":"Person3","age":37}'
 [x] Received '{"name":"Person4","age":37}'
 [x] Received '{"name":"Person5","age":37}'
 [x] Received '{"name":"Person6","age":37}'
 [x] Received '{"name":"Person7","age":37}'
 [x] Received '{"name":"Person8","age":37}'
 [x] Received '{"name":"Person9","age":37}'
 [x] Received '{"name":"Person10","age":37}'


For more information on RabbitMQ view the link below.

http://www.rabbitmq.com/


Friday, 18 January 2013

JMX URL for GemFire 7

In order to connect to the MBean server within a GemFire 7 Distributed System you would need to use a JMX service URL as follows.

Format:

service:jmx:rmi://{hotname}/jndi/rmi://{hostname}:1099/jmxrmi

Example:

service:jmx:rmi://Pas-Apicellas-MacBook-Pro.local/jndi/rmi://Pas-Apicellas-MacBook-Pro.local:1099/jmxrmi

Another way is to use GFSH and start jconsole issuing the command "start jconsole" as shown below. This will automatically connect for you providing you have the ability to display jconsole graphically.
  
gfsh>start jconsole
Running JDK JConsole


Viewing Data Distribution on GemFire Members

The following code can be used to show which member is hosting which primary piece of data in a partitioned region within GemFire. This was done with gemFire 7 but should work with GemFire 6.6 as well.

1. The server side cache.xml is as follows which pre populates some data into the region to save having to write a client to add data.
  
<?xml version="1.0"?>
<!DOCTYPE cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<cache>
    <cache-server port="40001" notify-by-subscription="true"/>
    <region name="exampleRegion">
      <region-attributes refid="PARTITION_REDUNDANT"/>
      <entry><key><string>1</string></key><value><string>MyValue1</string></value></entry>
      <entry><key><string>2</string></key><value><string>MyValue2</string></value></entry>
      <entry><key><string>3</string></key><value><string>MyValue3</string></value></entry>
      <entry><key><string>4</string></key><value><string>MyValue4</string></value></entry>
      <entry><key><string>5</string></key><value><string>MyValue5</string></value></entry>
      <entry><key><string>6</string></key><value><string>MyValue6</string></value></entry>
      <entry><key><string>7</string></key><value><string>MyValue7</string></value></entry>
      <entry><key><string>8</string></key><value><string>MyValue8</string></value></entry>
      <entry><key><string>9</string></key><value><string>MyValue9</string></value></entry>
      <entry><key><string>10</string></key><value><string>MyValue10</string></value></entry>
      <entry><key><string>11</string></key><value><string>MyValue11</string></value></entry>
      <entry><key><string>12</string></key><value><string>MyValue12</string></value></entry>
      <entry><key><string>13</string></key><value><string>MyValue13</string></value></entry>
      <entry><key><string>14</string></key><value><string>MyValue14</string></value></entry>
      <entry><key><string>15</string></key><value><string>MyValue15</string></value></entry>
      <entry><key><string>16</string></key><value><string>MyValue16</string></value></entry>
      <entry><key><string>17</string></key><value><string>MyValue17</string></value></entry>
      <entry><key><string>18</string></key><value><string>MyValue18</string></value></entry>
      <entry><key><string>19</string></key><value><string>MyValue19</string></value></entry>
      <entry><key><string>20</string></key><value><string>MyValue20</string></value></entry>
      <entry><key><string>21</string></key><value><string>MyValue21</string></value></entry>
      <entry><key><string>22</string></key><value><string>MyValue22</string></value></entry>
      <entry><key><string>23</string></key><value><string>MyValue23</string></value></entry>
      <entry><key><string>24</string></key><value><string>MyValue24</string></value></entry>
      <entry><key><string>25</string></key><value><string>MyValue25</string></value></entry>
      <entry><key><string>26</string></key><value><string>MyValue26</string></value></entry>
      <entry><key><string>27</string></key><value><string>MyValue27</string></value></entry>
      <entry><key><string>28</string></key><value><string>MyValue28</string></value></entry>
      <entry><key><string>29</string></key><value><string>MyValue29</string></value></entry>
      <entry><key><string>30</string></key><value><string>MyValue30</string></value></entry>
   </region>
</cache> 

2. When listing members we have one locator and 2 cache servers.
  
gfsh>list members;
  Name   | Id
-------- | -------------------------------------------------------
server2  | Pas-Apicellas-MacBook-Pro(server2:78035)<v2>:4641
server1  | Pas-Apicellas-MacBook-Pro(server1:78002)<v1>:13379
locator1 | Pas-Apicellas-MacBook-Pro(locator1:77992:locator):23631

3. Get a query to ensure we indeed have 30 entries in the region.
  
gfsh>query --query="select count(*) from /exampleRegion";

Result     : true
startCount : 0
endCount   : 20
Rows       : 1

Result
------
30

NEXT_STEP_NAME : END

4. Create an XML cache.xml file which will enable us to connect as a cache server to the Distributed System with storage disabled.
  
<?xml version="1.0"?>
<!DOCTYPE cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<cache>
  <cache-server port="0" />

  <region name="exampleRegion" >
       <region-attributes data-policy="partition" >
           <partition-attributes local-max-memory="0" redundant-copies="1"/>
           <subscription-attributes interest-policy="all"/>            
       </region-attributes>
  </region>
</cache> 

5. Write a java client with code as follows
  
package vmware.au.gemfire.demos.deptemp;

import java.util.Map;
import java.util.Set;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
import com.gemstone.gemfire.distributed.DistributedMember;

public class VerifyDataLocations 
{
 private Cache cache = null;
   
 public VerifyDataLocations() 
 {
     CacheFactory cf = new CacheFactory();
     cf.set("cache-xml-file", "xml/datalocations-cache-no-storage.xml");
     cf.set("locators", "localhost[10334]");
     cache = cf.create();
 }

 public void run() throws InterruptedException
 {
  Region<String,String> exampleRegion = cache.getRegion("exampleRegion");
  System.out.println("exampleRegion size = " + exampleRegion.size());

     Set<Map.Entry<String, String>> entries = exampleRegion.entrySet();

     for (Map.Entry entry: entries) 
     {

       DistributedMember member = 
         PartitionRegionHelper.getPrimaryMemberForKey(exampleRegion, (String) entry.getKey());
       System.out.println
         (String.format("\"Primary Member [Host=%s, Id=%s - Key=%s, Value=%s]", 
          member.getHost(), member.getId(), entry.getKey(), (String) entry.getValue())); 
        
     }
     
     System.out.println("Sleeping for 20 seconds..");
     
        cache.close();
     
 }
 
 /**
  * @param args
  * @throws InterruptedException 
  */
 public static void main(String[] args) throws InterruptedException 
 {
  // TODO Auto-generated method stub
  VerifyDataLocations test = new VerifyDataLocations();
  test.run();
 }

}

6. Output as follows.

exampleRegion size = 30
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=20, Value=MyValue20]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=21, Value=MyValue21]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=22, Value=MyValue22]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=23, Value=MyValue23]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=24, Value=MyValue24]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=25, Value=MyValue25]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=26, Value=MyValue26]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=27, Value=MyValue27]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=28, Value=MyValue28]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=29, Value=MyValue29]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=30, Value=MyValue30]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=1, Value=MyValue1]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=2, Value=MyValue2]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=3, Value=MyValue3]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server2:78035):4641 - Key=4, Value=MyValue4]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=5, Value=MyValue5]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=6, Value=MyValue6]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=7, Value=MyValue7]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=8, Value=MyValue8]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=9, Value=MyValue9]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=10, Value=MyValue10]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=11, Value=MyValue11]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=12, Value=MyValue12]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=13, Value=MyValue13]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=14, Value=MyValue14]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=15, Value=MyValue15]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=16, Value=MyValue16]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=17, Value=MyValue17]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=18, Value=MyValue18]
"Primary Member [Host=Pas-Apicellas-MacBook-Pro.local, Id=Pas-Apicellas-MacBook-Pro(server1:78002):13379 - Key=19, Value=MyValue19]




Tuesday, 15 January 2013

vFabric Gemfire 7 Monitoring Plugin (Hyperic)

Hyperic plug-in for vFabric Gemfire, manages GemFire Distributed System (DS) and the servers and services it comprises. Recenbtly a new version was released which supports GemFire 7. You can obtain it from the VMware Sulution Exchange link below.

https://solutionexchange.vmware.com/store/products/vfabric-gemfire-monitoring-plugin-hyperic

To set GemFire 7 monitoring on Hyperic 50 the steps are as follows
  • Download plugin from link above
  • If plugin name contains version such as vfgf-plugin-1.0.M1.jar, rename to vfgf-plugin.jar.
  • Log in to HQ UI
  • Click on Administration
  • Click on Plugin Manager
  • Click Add/Update Plugins
  • Select vfgf-plugin.jar from your filesystem
  • Click Ok
  • Wait for plugin sync to complete (usually not more than a minute or two)


  • Click on Resources
  • Click on the Tools menu
  • Click on New Platform
  • Enter a name for this platform such as "Gemfire 7.0" this name must be unique in HQ Inventory
  • Optionally enter Description and Location
  • From Platform Type drop down select either "vFabric Gemfire Distributed System 7.x"
  • Choose the HQ agent you wish to monitor gemfire from in the Agent Connection drop down. (Note: If the HQ agent will be monitoring GF remotely be sure firewall allows the selected HQ agent to connect to the gemfire agent/locators)
  • Enter the IP Address of the GemFire system into IP Address
  • Enter a unique name to use in the Fully Qualified Domain Name box. 
  • Once done it should look as follows once servers have been picked up and discovered.

  • Click OK - This will add the platform to inventory. It still needs to be configured 


  • Click on Edit under Configuration Properties under the Inventory tab of the new platform you added
  • Enter in the details for the locator(s) and their ports. If there are multiple locators then separate then by a comma.
Finally when done you can save charts to the main dashboard as required.


Wednesday, 19 December 2012

Spring Data JPA Repository with vFabric SQLFire

Spring JPA is part of the umbrella Spring Data project that makes it easy to easily implement JPA based repositories. In this example below we use Hibernate 4.1 as the JPA implementation along with with our Spring Data JPA repository to get up and running as quickly as possible. Finally in this example we use the SQLFire Hibernate Dialect given we are connecting to a SQLFire distributed database system. More info on the SQLFire Hibernate Dialect can be found here.

The project I have created in STS is as follows.


In no particular order lets show how we defined this project. Like most other blog entries this is based on the classic DEPT/EMP RDBMS tables. Before we start the maven STS project has the following defined. This will ensure you can use this code without compilation errors as all libraries required are defined with maven dependencies.

pom.xml
  
<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>spring-hibernate-jpa-sqlfire</groupId>
  <artifactId>spring-hibernate-jpa-sqlfire</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-hibernate-jpa-sqlfire</name>
   <properties>
       <spring.version>3.1.2.RELEASE</spring.version>
   </properties>
  <dependencies>
   <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.6.Final</version>
   </dependency>
   <dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.0-api</artifactId>
    <version>1.0.0.Final</version>
   </dependency>   
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
   </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jpa</artifactId>
    <version>2.0.8</version>
   </dependency>
   <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.2</version>
   </dependency>
     <dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-jpa</artifactId>
     <version>1.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.vmware</groupId>
      <artifactId>sqlf-client</artifactId>
      <version>1.0.3</version>
      <scope>system</scope>
      <systemPath>/Users/papicella/sqlfire/vFabric_SQLFire_103/lib/sqlfireclient.jar</systemPath>
    </dependency>
    <dependency>
      <groupId>com.vmware</groupId>
      <artifactId>sqlf-dialect</artifactId>
      <version>1.0.3</version>
      <scope>system</scope>
      <systemPath>/Users/papicella/sqlfire/vFabric_SQLFire_103/lib/sqlfHibernateDialect.jar</systemPath>
    </dependency>
  </dependencies>   
    
</project>
1. Create a persistence.xml file in META-INF as shown below.

persistence.xml
  
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">

 <persistence-unit name="application" transaction-type="RESOURCE_LOCAL">
     <mapping-file>META-INF/persistence-query.xml</mapping-file>
        <class>pas.au.spring.hibernate.sqlfire.model.Dept</class>
        <class>pas.au.spring.hibernate.sqlfire.model.Emp</class>
  <exclude-unlisted-classes>true</exclude-unlisted-classes>
 </persistence-unit>

</persistence> 

2. Optionally created named queries in it's own XML. I prefer to do this then add annotations as this gives you the ability to tweak the queries without altering the code.

persistence-query.xml
  
<?xml version="1.0" encoding="UTF-8" ?>
 
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
        version="1.0">

    <named-query name="Dept.findByDeptnoNamedQuery">
        <query>
            from Dept
            where deptno = ?1
        </query>
    </named-query>
        
</entity-mappings>

3. Create the Dept and Emp domain model classes as shown below. These are referenced in persistence.xml above.

Dept.java
  
package pas.au.spring.hibernate.sqlfire.model;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Dept 
{
 @Id
 @GeneratedValue (strategy=GenerationType.IDENTITY)
 @Column(name="deptno")
 private Long deptno;
 
 @Column(length = 20, unique = true)
 private String dname;
 
 private String loc;

    @OneToMany(mappedBy = "dept", fetch = FetchType.EAGER)
    private List<Emp> empList;

 public Dept()
 { 
 }
 
 public Dept(Long deptno, String dname, String loc) 
 {
  super();
  this.deptno = deptno;
  this.dname = dname;
  this.loc = loc;
 }

 public Long getDeptno() {
  return deptno;
 }

 public void setDeptno(Long deptno) {
  this.deptno = deptno;
 }

 public String getDname() {
  return dname;
 }

 public void setDname(String dname) {
  this.dname = dname;
 }

 public String getLoc() {
  return loc;
 }

 public void setLoc(String loc) {
  this.loc = loc;
 }

 
    public List<Emp> getEmpList() {
  return empList;
 }

 public void setEmpList(List<Emp> empList) {
  this.empList = empList;
 }

 public Emp addEmp(Emp emp) {
        getEmpList().add(emp);
        emp.setDept(this);
        return emp;
    }

    public Emp removeEmp(Emp emp) {
        getEmpList().remove(emp);
        emp.setDept(null);
        return emp;
    }

 @Override
 public String toString() {
  return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc
    + "]";
 }
 
} 
Emp.java
  
package pas.au.spring.hibernate.sqlfire.model;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Emp 
{
 @Id
 @GeneratedValue (strategy=GenerationType.IDENTITY)
 @Column(name="empno")
 private Long empno;
 
 @Column(length = 20)
 private String ename;

 private Timestamp hiredate;
    private String job;
    private Long mgr;
    private Double sal;
    @ManyToOne
    @JoinColumn(name = "DEPTNO")
    private Dept dept;
    
    public Emp()
    {
    }

 public Emp(Long empno, String ename, String job, Long mgr, Double sal, Timestamp hiredate, Dept dept) {
  super();
  this.empno = empno;
  this.ename = ename;
  this.job = job;
  this.mgr = mgr;
  this.sal = sal;
  this.hiredate = hiredate;
  this.dept = dept;
 }

 public Long getEmpno() {
  return empno;
 }

 public void setEmpno(Long empno) {
  this.empno = empno;
 }

 public String getEname() {
  return ename;
 }

 public void setEname(String ename) {
  this.ename = ename;
 }

 public String getJob() {
  return job;
 }

 public void setJob(String job) {
  this.job = job;
 }

 public Long getMgr() {
  return mgr;
 }

 public void setMgr(Long mgr) {
  this.mgr = mgr;
 }

 public Double getSal() {
  return sal;
 }

 public void setSal(Double sal) {
  this.sal = sal;
 }

 public Dept getDept() {
  return dept;
 }

 public void setDept(Dept dept) {
  this.dept = dept;
 }

 public Timestamp getHiredate() {
  return hiredate;
 }

 public void setHiredate(Timestamp hiredate) {
  this.hiredate = hiredate;
 }

 @Override
 public String toString() {
  return "Emp [empno=" + empno + ", ename=" + ename + ", hiredate="
    + hiredate + ", job=" + job + ", mgr=" + mgr + ", sal=" + sal
    + ", dept=" + dept + "]";
 }
 
} 
4. Create a spring XML file in the META-INF/spring directory named "applicationContext-persistence.xml"

applicationContext-persistence.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:tx="http://www.springframework.org/schema/tx"
 xmlns:repository="http://www.springframework.org/schema/data/repository"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
 xsi:schemaLocation="http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.4.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="persistenceUnitName" value="application" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">com.vmware.sqlfire.hibernate.SQLFireDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.driver_class">com.vmware.sqlfire.jdbc.ClientDriver</prop>
                <prop key="hibernate.connection.url">jdbc:sqlfire://localhost:1527</prop>
                <prop key="hibernate.connection.username">APP</prop>
                <prop key="hibernate.connection.password">APP</prop>
            </props>
        </property>
        <property name="packagesToScan" value="pas.au.spring.hibernate.sqlfire.repository" />
    </bean>
 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
 
    <tx:annotation-driven/>

 
 <!-- CRUD JPA Repositories Here loaded by default  -->
 <jpa:repositories base-package="pas.au.spring.hibernate.sqlfire.repository" />
 
</beans>

5. Create a JPA CRUD repository as shown below. This will automatically be picked up by spring JPA repository component scanner as defined in "applicationContext-persistence.xml" above.

JPADeptRepository.java
  
package pas.au.spring.hibernate.sqlfire.repository;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import pas.au.spring.hibernate.sqlfire.model.Dept;

/*
 * Define a repository with all CRUD methods written for you
 */
public interface JPADeptRepository extends CrudRepository<Dept, Long>
{
 /*
  * Method which will invoke the JPQL required for a find by the attribute name
  */
 public Dept findByDeptno (Long deptno);
 
 /* 
  * Shows how to access  a named query using a method name to identify it
  * The method name must match the defined query name
  * 
  */
 public Dept findByDeptnoNamedQuery (Long deptno);

 /*
  * Method that allows us to supply a JPQL query to execute for the method
  */
 @Query("SELECT d FROM Dept d WHERE d.dname LIKE '%'")
    public List<Dept> findDeptsWithCustomJPQLQuery();

 /*
  * Method that allows us to supply a JPQL query to execute for the method with a parameter
  */
 @Query("SELECT d FROM Dept d WHERE d.loc = ?1")
    public Dept findDeptWithCustomJPQLQueryWithParam(String loc);
 
 @Query("SELECT d FROM Dept d WHERE d.deptno = ?1")
 public Dept findEmpsInDeptno (Long deptno);
 
 @Query(value = "SELECT * FROM DEPT where deptno = ?1", nativeQuery = true)
 public Dept findDeptByNativeQuery(Long deptno);
 
 @Query(value = "SELECT d, e FROM Dept d, Emp e where e.dept = d and d.deptno = ?1")
 public List<Object[]> findWithJoin(Long deptno);

} 

6. Finally create a test class to verify the repository. It's assumed you have SQLFire running and the DEPT/EMP table already exist. You can use this previous blog entry to get that setup.

http://theblasfrompas.blogspot.com.au/2011/12/sqlfire-in-few-minutes.html

JPAReposDeptTest.java
  
package pas.au.spring.hibernate.sqlfire.test.repository;

import static org.junit.Assert.*;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import pas.au.spring.hibernate.sqlfire.repository.JPADeptRepository;
import pas.au.spring.hibernate.sqlfire.model.Dept;
import pas.au.spring.hibernate.sqlfire.model.Emp;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/applicationContext-persistence.xml")
public class JPAReposDeptTest 
{
 @Autowired
 JPADeptRepository deptRespository;
 
 @Test
 public void invokeFindAll() 
 {
  List<Dept> deps = (List<Dept>) deptRespository.findAll();
  
  System.out.println("deps size = " + deps.size());
  assertNotNull(deps);
 }

 @Test
 public void invokeFindOne() 
 {
  Dept dept = deptRespository.findOne(new Long(20));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(20), dept.getDeptno());
 }
 
 @Test
 public void invokeFindByDeptno() 
 {
  Dept dept = deptRespository.findByDeptno(new Long(10));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(10), dept.getDeptno());
 }

 @Test
 public void invokeNamedQuery() 
 {
  Dept dept = deptRespository.findByDeptnoNamedQuery(new Long(30));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(30), dept.getDeptno());
 }

 @Test
 public void invokefindDeptsWithCustomJPQLQuery() 
 {
  List<Dept> deps = (List<Dept>) deptRespository.findDeptsWithCustomJPQLQuery();
  
  System.out.println("deps size = " + deps.size());
  assertNotNull(deps);
 }

 @Test
 public void invokefindDeptsWithCustomJPQLQueryWithParam() 
 {
  Dept dept = deptRespository.findDeptWithCustomJPQLQueryWithParam("CHICAGO");
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(30), dept.getDeptno());
 }

 @Test
 public void invokefindEmpInDeptno() 
 {
  Dept dept = deptRespository.findEmpsInDeptno(new Long(20));
  
  System.out.println(dept);
  assertNotNull(dept);
  
  List<Emp> emps = dept.getEmpList();
  for (Emp e: emps)
  {
   System.out.println(e);
  }
  
  assertEquals(5, emps.size());
 }
 
 @Test
 public void invokeFindDeptByNativeQuery()
 {
  Dept dept = deptRespository.findDeptByNativeQuery(new Long(40));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(40), dept.getDeptno());  
 }
 
 @Test
 public void invokeFindWithJoin()
 {
  List<Object[]> results = deptRespository.findWithJoin(new Long(10));
  
  System.out.println("Size of results = " + results.size());
  assertEquals(3, results.size());
  
  for (Object[] result: results)
  {
   System.out.println("Dept: " + result[0] + ", Emp: " + result[1]);
  }
  
 }
}

7. Run the test class above.

Verify output as shown below.



Dec 19, 2012 9:11:41 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
Dec 19, 2012 9:11:41 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate:
    select
        dept0_.deptno as deptno0_,
        dept0_.dname as dname0_,
        dept0_.loc as loc0_
    from
        Dept dept0_
Hibernate:
    select
        emplist0_.DEPTNO as DEPTNO0_1_,
        emplist0_.empno as empno1_,
        emplist0_.empno as empno1_0_,
        emplist0_.DEPTNO as DEPTNO1_0_,
        emplist0_.ename as ename1_0_,
        emplist0_.hiredate as hiredate1_0_,
        emplist0_.job as job1_0_,
        emplist0_.mgr as mgr1_0_,
        emplist0_.sal as sal1_0_
    from
        Emp emplist0_
    where
        emplist0_.DEPTNO=?

.......
Size of results = 3
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7934, ename=MILLER, hiredate=1982-01-23 00:00:00.0, job=CLERK, mgr=7782, sal=1300.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7782, ename=CLARK, hiredate=1981-06-09 00:00:00.0, job=MANAGER, mgr=7839, sal=2450.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7839, ename=KING, hiredate=1981-11-17 00:00:00.0, job=PRESIDENT, mgr=null, sal=5000.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]


More Information on Spring data JPA and SQLFire Hibernate Dialect can be can be found here.

Spring Data JPA
http://www.springsource.org/spring-data/jpa

vFabric SQLFire Hibernate Dialect
http://communities.vmware.com/docs/DOC-20294


Friday, 7 December 2012

GemFire 70 - Gemcached client adapter for Memcache

As part of GemFire 70 Gemcached is a vFabric GemFire adapter that allows memcached clients to communicate with a GemFire server cluster, as if the servers were memcached servers. Memcached is an open-source caching solution that uses a distributed, in-memory hash map to store key-value pairs of string or object data.

In this example below we are using the following

GemFire 70
SpyMemcache JAVA API

1. Start a GemFire 70 cluster as shown below. We are ommitting the files required here but this shows what is required to ensure Memcache clients can connect to GemFire. Simple unix script below.

gfsh <<!
start locator --name=locator1 --properties-file=gemfire.properties --bind-address=localhost --port=10334 --dir=locator;
start server --name=server1 --memcached-port=11211 --memcached-protocol=BINARY --properties-file=gemfire.properties --locators=localhost[10334] --dir=server1
start server --name=server2 --memcached-port=11212 --memcached-protocol=BINARY --properties-file=gemfire.properties --locators=localhost[10334] --dir=server2
list members;
list regions;
exit;
!


2. Verify we have Memcache ports established and running

[Fri Dec 07 13:10:48 papicella@:~/gf7/gemcache ] $ ./memcache-status.sh
tcp4       0      0  10.117.85.71.11212     *.*                    LISTEN    
tcp4       0      0  10.117.85.71.11211     *.*                    LISTEN    
udp4       0      0  *.62112                *.*   
                           

3. Create a java client as follows which connects to the Gemcached servers we have in our cluster
  
package vmware.au.gemfire.demos.gemcached;

import net.spy.memcached.AddrUtil;
import net.spy.memcached.BinaryConnectionFactory;
import net.spy.memcached.MemcachedClient;

public class GemcacheClient 
{

 private MemcachedClient c = null;
 
 public GemcacheClient() throws Exception
 {
  c = new MemcachedClient(new BinaryConnectionFactory(),
          AddrUtil.getAddresses("10.117.85.71:11212 10.117.85.71:11212"));  
 }
 
 public void run()
 {

  for (int i = 1; i <= 20; i++)
  {
   c.set(String.valueOf(i), 0, "Customer" + i);
  }
  
  System.out.println("added 20 entries \n");
  
  String value =  (String) c.get("5");
  
  System.out.println("Value with key [5] = " + value);
  
  c.shutdown();  
 }
 
 /**
  * @param args
  * @throws Exception 
  */
 public static void main(String[] args) throws Exception 
 {
  GemcacheClient test = new GemcacheClient();
  test.run();
  System.out.println("all done..");
 }

}

4. Run it and verify output as shown below. Ensure you alter the connect address correctly.

2012-12-07 13:25:05.577 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=/10.117.85.71:11212, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2012-12-07 13:25:05.578 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=/10.117.85.71:11212, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2012-12-07 13:25:05.582 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@52cc95d
2012-12-07 13:25:05.584 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@4393722c
added 20 entries

Value with key [5] = Customer5
2012-12-07 13:25:05.942 INFO net.spy.memcached.MemcachedConnection:  Shut down memcached client
all done..


5. Now in GFSH verify we have a region called "gemcached" and it now has data.

  
[Fri Dec 07 13:40:27 papicella@:~/gf7/gemcache ] $ gfsh
WARNING: JDK/lib/tools.jar is required for some GFSH commands. Please set JAVA_HOME to point to the JDK directory. Currently using JRE.
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  / 
 / /__/ / ____/  _____/ / /    / /  
/______/_/      /______/_/    /_/    v7.0

Monitor and Manage GemFire
gfsh>connect --locator=localhost[10334];
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=Pas-Apicellas-MacBook-Pro.local, port=1099] ..
Successfully connected to: [host=Pas-Apicellas-MacBook-Pro.local, port=1099]

gfsh>list regions;
List of regions
---------------
gemcached
test

gfsh>query --query="select count(*) from /gemcached";

Result     : true
startCount : 0
endCount   : 20
Rows       : 1

Result
------
20

NEXT_STEP_NAME : END 

More information can be found in the documentation below.

http://pubs.vmware.com/vfabricNoSuite/index.jsp?topic=/com.vmware.vfabric.gemfire.7.0/tools_modules/gemcached/deploying_gemcached.html

Thursday, 29 November 2012

GemFire 70 and Parallel WAN and Simplified WAN Configuration

With the introduction of GemFire 70 the WAN replication has been simplified. IN fact the simplest setup is as shown below.

1. A cache sever started with a cache.xml as follows which defines a single sender and a receiver
  
<?xml version="1.0"?>
<!DOCTYPE cache PUBLIC
    "-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN"
    "http://www.gemstone.com/dtd/cache7_0.dtd">

<cache>
    <gateway-sender id="sender1" parallel="true" remote-distributed-system-id="2" dispatcher-threads="2" order-policy="partition"/>
    <gateway-receiver start-port="1530" end-port="1551"/>
    <cache-server port="40001"/>
    <region name="wantest">
        <region-attributes refid="PARTITION" gateway-sender-ids="sender1"/>
    </region>
</cache>

2. Some commands in GFSH to verify the gateway senders/recievers
  
Cluster-1 gfsh>list gateways
Gateways


GatewaySender

GatewaySender Id |                       Member                       | Remote Cluster Id |   Type   | Status  | Queued Events | Receiver Location
---------------- | -------------------------------------------------- | ----------------- | -------- | ------- | ------------- | -----------------
sender1          | Pas-Apicellas-MacBook-Pro(server1:22361)<v1>:10766 | 2                 | Parallel | Running | 0             | null
sender1          | Pas-Apicellas-MacBook-Pro(server2:22362)<v2>:25822 | 2                 | Parallel | Running | 0             | null


GatewayReceiver

                      Member                       | Port | Sender Count | Sender's Connected
-------------------------------------------------- | ---- | ------------ | ------------------------------------------------------
Pas-Apicellas-MacBook-Pro(server1:22361)<v1>:10766 | 1541 | 2            | ["Pas-Apicellas-MacBook-Pro(server1:22385)<v1>:55223"]
Pas-Apicellas-MacBook-Pro(server2:22362)<v2>:25822 | 1537 | 2            | ["Pas-Apicellas-MacBook-Pro(server2:22386)<v2>:11991"]

Cluster-1 gfsh>status gateway-sender --id=sender1

                      Member                       |   Type   | Status
-------------------------------------------------- | -------- | -------
Pas-Apicellas-MacBook-Pro(server1:22361)<v1>:10766 | Parallel | Running
Pas-Apicellas-MacBook-Pro(server2:22362)<v2>:25822 | Parallel | Running 

More information on this can be found at the following link

http://pubs.vmware.com/vfabricNoSuite/index.jsp?topic=/com.vmware.vfabric.gemfire.7.0/topologies_and_comm/multi_site_configuration/setting_up_a_multisite_system.html

Thursday, 22 November 2012

Spring data repository for GemFire 7

The example below shows the various config and code required to use Spring Data Repository with GemFire7. It is assumed we have a GemFire distributed system up and running with some department and employee data. For this example we will connect as a client proxy where all requests go to the server side for processing.

client.xml - client cache file for access to the remote servers
  
<!DOCTYPE client-cache PUBLIC 
"-//GemStone Systems, Inc.//GemFire Declarative Caching 7//EN" 
"http://www.gemstone.com/dtd/cache7_0.dtd">
<client-cache>	
	<!-- No cache storage in the client region because of the PROXY client region shortcut setting. -->

    <region name="departments">
      <region-attributes refid="PROXY" pool-name="gfPool"/>
    </region>   
		
    <region name="employees">
		<region-attributes refid="PROXY" pool-name="gfPool" />
    </region>
</client-cache>

application-context.xml - spring application context file using spring gemfire. It's here where we make a connection to GemFire through a locator to load balance between the servers.
  
<?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"
	xmlns:gfe-data="http://www.springframework.org/schema/data/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
		http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.2.xsd">
		
	<gfe:client-cache id="client-cache" cache-xml-location="classpath:client.xml" pool-name="gfPool"/>
	
	<gfe:pool id="gfPool" max-connections="10">
		<gfe:locator host="localhost" port="10334"/>
	</gfe:pool>
	
	<gfe:lookup-region id="departments" name="departments" cache-ref="client-cache"/>
   	<gfe:lookup-region id="employees" name="employees" cache-ref="client-cache"/>

	<gfe-data:repositories base-package="vmware.au.se.gf7.deptemp.repos"  />
   
</beans>

Department.java - domain object with spring data repository annotation referencing "departments" region in gemFire
  
package vmware.au.se.gf7.deptemp.beans;

import java.io.Serializable;
import java.util.Properties;

import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;

import com.gemstone.gemfire.cache.Declarable;

@Region("departments")
public class Department implements Declarable, Serializable
{

	private static final long serialVersionUID = -9097335119586059309L;

	@Id
	private int deptno;
	private String name;
	
	public void init(Properties props) 
	{
		// TODO Auto-generated method stub
		this.deptno = Integer.parseInt(props.getProperty("deptno"));
		this.name = props.getProperty("name");
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Department [deptno=" + deptno + ", name=" + name + "]";
	}
  
}

Employee.java - domain object with spring data repository annotation referencing "employees" region in GemFire
  
package vmware.au.se.gf7.deptemp.beans;

import java.io.Serializable;
import java.util.Properties;

import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;

import com.gemstone.gemfire.cache.Declarable;

@Region("employees")
public class Employee implements Declarable, Serializable
{

	private static final long serialVersionUID = -8229531542107983344L;
	
	@Id
	private int empno;
	private String name;
	private String job;
	private int deptno;

	public void init(Properties props) 
	{
		// TODO Auto-generated method stub
		this.empno = Integer.parseInt(props.getProperty("empno"));
		this.name = props.getProperty("name");
		this.job = props.getProperty("job");
		this.deptno = Integer.parseInt(props.getProperty("deptno"));
		
	}

	public int getEmpno() {
		return empno;
	}

	public void setEmpno(int empno) {
		this.empno = empno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getJob() {
		return job;
	}

	public void setJob(String job) {
		this.job = job;
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	@Override
	public String toString() {
		return "Employee [empno=" + empno + ", name=" + name + ", job=" + job
				+ ", deptno=" + deptno + "]";
	}
	
	
	
} 

At this point we create two repositories as shown below.

DeptRepository.java
  
package vmware.au.se.gf7.deptemp.repos;

import java.util.Collection;

import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.repository.CrudRepository;
import vmware.au.se.gf7.deptemp.beans.Department;

public interface DeptRepository extends CrudRepository<Department, String> 
{
	Department findByName(String name);
	
	@Query("SELECT * FROM /departments")
	Collection<Department> myFindAll();
} 

EmpRepository.java
  
package vmware.au.se.gf7.deptemp.repos;

import java.util.Collection;

import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.repository.CrudRepository;

import vmware.au.se.gf7.deptemp.beans.Employee;

public interface EmpRepository extends CrudRepository<Employee, String>
{
	@Query("SELECT * FROM /employees where deptno = $1")
	Collection<Employee> empsInDeptno(int deptno);
	
	@Query("SELECT * FROM /employees")
	Collection<Employee> myFindAll();
}

Finally we have a Test client as follows.
  
package spring.gemfire.repository.test;

import java.util.Collection;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import vmware.au.se.gf7.deptemp.beans.Department;
import vmware.au.se.gf7.deptemp.beans.Employee;
import vmware.au.se.gf7.deptemp.repos.DeptRepository;
import vmware.au.se.gf7.deptemp.repos.EmpRepository;

public class Test 
{

	private ConfigurableApplicationContext ctx = null;
	
	public Test()
	{
		ctx = new ClassPathXmlApplicationContext("application-context.xml");		
	}
	
	public void run()
	{
		
		DeptRepository deptRepos = (DeptRepository) ctx.getBean(DeptRepository.class);
        
		// get quick size
		System.out.println("** Size of dept repository **");
		System.out.println("Size = " + deptRepos.count());
		
		// call findOne crud method by key
		System.out.println("** calling  deptRepos.findOne(\"20\") **");
		Department dept = (Department) deptRepos.findOne("20");
		System.out.println(dept);

		// call findOne crud method for an attribute
		System.out.println("** calling  deptRepos.findByName(\"ACCOUNTING\") **");
		Department dept2 = (Department) deptRepos.findByName("ACCOUNTING");
		System.out.println(dept2);
		
		// call my own findAll
		Collection<Department> deps = (Collection<Department>) deptRepos.myFindAll(); 
		
		System.out.println("\n** All Departments using -> deptRepos.myFindAll()");
		System.out.println("Defined as : @Query(\"SELECT * FROM /departments\") ");
		System.out.println("Collection<Department> myFindAll(); ** ");
		
		for (Department d: deps)
		{
			System.out.println(d.toString());
		}
		
		EmpRepository empRepos = (EmpRepository) ctx.getBean(EmpRepository.class);

		// get quick size
		System.out.println("** Size of emp repository **");
		System.out.println("Size = " + empRepos.count());
		
		Collection<Employee> emps = empRepos.empsInDeptno(40);
		System.out.println("\n ** All Employees in dept 40 using -> Collection<Employee> empsInDeptno(int deptno) **");
		for (Employee e: emps)
		{
			System.out.println(e.toString());
		}
		
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		Test t = new Test();
		t.run();
		System.out.println("all done..");
		
	}

}


Output is as follows

[info 2012/11/22 16:39:03.626 EST tid=0xf] AutoConnectionSource discovered new locators [192-168-1-3.tpgi.com.au/192.168.1.3:10334]

[config 2012/11/22 16:39:03.628 EST tid=0x10] Updating membership port.  Port changed from 0 to 59,207.
** Size of dept repository **
Size = 4
** calling  deptRepos.findOne("20") **
Department [deptno=20, name=RESEARCH]
** calling  deptRepos.findByName("ACCOUNTING") **
Department [deptno=10, name=ACCOUNTING]

** All Departments using -> deptRepos.myFindAll()
Defined as : @Query("SELECT * FROM /departments")
Collection myFindAll(); **
Department [deptno=30, name=SALES]
Department [deptno=40, name=OPERATIONS]
Department [deptno=10, name=ACCOUNTING]
Department [deptno=20, name=RESEARCH]
** Size of emp repository **
Size = 13

 ** All Employees in dept 40 using -> Collection empsInDeptno(int deptno) **
Employee [empno=7380, name=BLACK, job=CLERK, deptno=40]
Employee [empno=7381, name=BROWN, job=SALESMAN, deptno=40]
Employee [empno=7373, name=SIENA, job=CLERK, deptno=40]
all done..


For more information see the link below.

http://static.springsource.org/spring-gemfire/docs/current/reference/html/gemfire-repositories.html

Tuesday, 20 November 2012

Management of GemFire 7 using gfsh command line interface

The GemFire command line interface or 'gfsh' (pronounced "gee - fish") provides a single interface that allows you to launch, manage and monitor vFabric GemFire processes, data and applications.

The GemFire 7.0 version of gfsh supports all of the commands that existed in the previous version of gfsh (released with GemFire 6.6) and also now includes functionality that was previously found in the gemfire and cacheserver scripts.
With gfsh, you can:

  • Start and stop GemFire processes, such as locators and cache servers
  • Start and stop Gateway Senders and Gateway Receiver processes
  • Deploy applications
  • Create and destroy regions
  • Execute functions
  • Manage disk stores
  • Import and export data
  • Monitor GemFire processes
  • Launch GemFire monitoring tools 
Here is a quick example of how it works.

1. Setup your environment to use GemFire 70 as shown below

export GEMFIRE=/Users/papicella/gemfire/vFabric_GemFire_70_b38623

export GF_JAVA=$JAVA_HOME/bin/java

export PATH=$PATH:$JAVA_HOME/bin:$GEMFIRE/bin

export CLASSPATH=$GEMFIRE/lib/gemfire.jar:$GEMFIRE/lib/antlr.jar:\
$GEMFIRE/lib/gfsh-dependencies.jar:$GEMFIRE/lib/gfSecurityImpl.jar:\
$GEMFIRE/lib/jackson-core-asl-1.9.9.jar:\
$GEMFIRE/lib/commons-logging.jar:\
$GEMFIRE/lib/tomcat-embed-core.jar:\
$GEMFIRE/lib/tomcat-embed-logging-juli.jar:\
$GEMFIRE/lib/tomcat-embed-jasper.jar:\
$CLASSPATH

echo ""
echo "CLASSPATH as follows..."
echo ""

echo $CLASSPATH


2. Start gfsh as shown below.
  
[Tue Nov 20 11:02:51 papicella@:~/vmware/ant-demos/gemfire/70/Demo ] $ gfsh
WARNING: JDK/lib/tools.jar is required for some GFSH commands. Please set JAVA_HOME to point to the JDK directory. Currently using JRE.
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  / 
 / /__/ / ____/  _____/ / /    / /  
/______/_/      /______/_/    /_/    v7.0

Monitor and Manage GemFire
gfsh>

3. Start a locator as shown below

start locator --name=locator1 --properties-file=gemfire.properties --bind-address=localhost --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator
  
gfsh>start locator --name=locator1 --properties-file=gemfire.properties --bind-address=localhost --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator
Starting a Locator in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator on localhost[10334] as locator1...
.....................................
Locator in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator on 192-168-1-3.tpgi.com.au[10334] as locator1 is currently online.
Process ID: 4686
Uptime: 19 seconds
GemFire Version: 7.0
Java Version: 1.6.0_35
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator/locator1.log
JVM Arguments: -DgemfirePropertyFile=gemfire.properties -Dgemfire.launcher.registerSignalHandlers=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/ecj-3.7.2.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/spring-asm-3.1.1.RELEASE.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfSecurityImpl.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/jackson-core-asl-1.9.9.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/commons-logging.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar::

Successfully connected to: [host=192-168-1-3.tpgi.com.au, port=1099]

4. Start 2 peers as shown below

start server --name=peer1 --cache-xml-file=Pulse.xml --properties-file=gemfire.properties --locators=localhost[10334] --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1

start server --name=peer2 --cache-xml-file=Pulse.xml --properties-file=gemfire.properties --locators=localhost[10334] --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2


  
gfsh>start server --name=peer1 --cache-xml-file=Pulse.xml --properties-file=gemfire.properties --locators=localhost[10334] --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1
Starting a Cache server in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1 on 192-168-1-3.tpgi.com.au[40404] as peer1...
.....
Server in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1 on 192-168-1-3.tpgi.com.au[40001] as peer1 is currently online.
Process ID: 4687
Uptime: 2 seconds
GemFire Version: 7.0
Java Version: 1.6.0_35
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1/peer1.log
JVM Arguments: -Dgemfire.default.locators=192.168.1.3[10334] -DgemfirePropertyFile=gemfire.properties -Dgemfire.cache-xml-file=Pulse.xml -Dgemfire.locators=localhost[10334] -Dgemfire.launcher.registerSignalHandlers=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/ecj-3.7.2.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/spring-asm-3.1.1.RELEASE.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfSecurityImpl.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/jackson-core-asl-1.9.9.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/commons-logging.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar::

gfsh>start server --name=peer2 --cache-xml-file=Pulse.xml --properties-file=gemfire.properties --locators=localhost[10334] --dir=/Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2
Starting a Cache server in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2 on 192-168-1-3.tpgi.com.au[40404] as peer2...
.....
Server in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2 on 192-168-1-3.tpgi.com.au[40002] as peer2 is currently online.
Process ID: 4688
Uptime: 2 seconds
GemFire Version: 7.0
Java Version: 1.6.0_35
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2/peer2.log
JVM Arguments: -Dgemfire.default.locators=192.168.1.3[10334] -DgemfirePropertyFile=gemfire.properties -Dgemfire.cache-xml-file=Pulse.xml -Dgemfire.locators=localhost[10334] -Dgemfire.launcher.registerSignalHandlers=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/ecj-3.7.2.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/spring-asm-3.1.1.RELEASE.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gemfire.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/antlr.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfsh-dependencies.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/gfSecurityImpl.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/jackson-core-asl-1.9.9.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/commons-logging.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-core.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-logging-juli.jar:/Users/papicella/gemfire/vFabric_GemFire_70_b38623/lib/tomcat-embed-jasper.jar::

5. Start Pulse to monitor the cluster over a HTTP browser

start pulse
  
gfsh>start pulse;
Running GemFire Pulse Pulse URL : http://192.168.1.3:8083/pulse/

6. The HTTP browser should be invoked where you can connect to an embedded pulse server to monitor the cluster. The username / password for this is admin/admin, Once logged in should look as follows


7. Now lets stop the system as shown below.

  
gfsh>stop server --name=peer2;
Stopping Cache Server running in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2 on 192-168-1-3.tpgi.com.au[40002] as peer2...
Process ID: 4688
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer2/peer2.log
....
gfsh>stop server --name=peer1;
Stopping Cache Server running in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1 on 192-168-1-3.tpgi.com.au[40001] as peer1...
Process ID: 4687
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/peer1/peer1.log
....
gfsh>stop locator --name=locator1;
Stopping Locator running in /Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator on 192-168-1-3.tpgi.com.au[10334] as locator1...
Process ID: 4686
Log File: /Users/papicella/vmware/ant-demos/gemfire/70/Demo/locator/locator1.log
...
No longer connected to 192-168-1-3.tpgi.com.au[1099].

For more information about GemFire 70 gfsh command line options / commands you can just use the tab key in the shell. One example you can use to get an overview of metrics is as follows

  
gfsh>show metrics;

Cluster-wide Metrics

 Type   |        Metric         | Value
------- | --------------------- | -----
cluster | totalHeapSize         | 246
cache   | totalRegionEntryCount | 0
        | totalRegionCount      | 2
        | totalMissCount        | 0
        | totalHitCount         | 22454
        | diskReadsRate         | 0
        | diskWritesRate        | 0
        | flushTimeAvgLatency   | 0
        | totalBackupInProgress | 0
query   | activeCQCount         | 0
        | queryRequestRate      | 0

More information on gfsh can be found in the GemFire 70 documentation link below.

http://pubs.vmware.com/vfabricNoSuite/index.jsp?topic=/com.vmware.vfabric.gemfire.7.0/tools_modules/gfsh/chapter_overview.html