---
title: Sample REST Applications
---

<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

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

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

<a id="topic_lvp_cd5_m4"></a>


This section provides examples that illustrate how multiple clients, both REST and native, can access the same <%=vars.product_name%> region data.

**Note:**
You must set PDX read-serialized to true when starting the cache server to achieve interoperability between different clients. See [Setup and Configuration](setup_config.html#topic_e21_qc5_m4) for instructions on starting up REST-enabled cache servers.

The following examples demonstrate the following:

1.  A Java REST client creates a Person object on key 1. This client references the following supporting examples (also provided):
    1.  <%=vars.product_name%> cache client
    2.  REST client utility
    3.  Date Time utility
    4.  Person class
    5.  Gender class

2.  A Ruby REST client also gets data for key 1 and updates it.
3.  A Python REST Client demonstrates the creation and modification of objects.
    **Note:**
    An additional Python REST client reference application is available here: [https://github.com/gemfire/py-gemfire-rest](https://github.com/gemfire/py-gemfire-rest).

The following Java examples assume a project directory structure similar to the following:

<img src="../images/rest_example_java_packages.png" id="topic_lvp_cd5_m4__image_rvd_ydd_3r" class="image" />
## \#1. REST Java Client (RestClientApp.java)

``` pre
package org.apache.geode.restclient;

 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.HttpServerErrorException;

 import org.apache.geode.util.RestClientUtils;

 import java.util.ArrayList;
 import java.util.List;

@SuppressWarnings( "unused")
 public class RestClientApp  {
   private static final String PEOPLE_REGION =  "/People";

   private static final String PERSON1_AS_JSON =  "{"
          +  "\"@type\ ": \"org.apache.geode.domain.Person\ "," +  "\"id\ ": 1,"
       +  " \"firstName\ ": \"Jane\ "," +  " \"middleName\ ": \"H\ ","
       +  " \"lastName\ ": \"Doe1\ "," +  " \"birthDate\ ": \"04/12/1983\ ","
       +  "\"gender\ ": \"MALE\ "" + "}";

   public static void main( final String... args)  throws Exception {
    doCreate(PEOPLE_REGION,  "1");
     System.out.println( "Programme has run successfully...!");
  }

   private static  HttpHeaders setAcceptAndContentTypeHeaders(){
    List<MediaType> acceptableMediaTypes =  new ArrayList<MediaType>();
    acceptableMediaTypes.add(MediaType.APPLICATION_JSON);

    HttpHeaders headers =  new HttpHeaders();
    headers.setAccept(acceptableMediaTypes);
    headers.setContentType(MediaType.APPLICATION_JSON);
     return headers;
  }

   private static void doCreate( final String regionNamePath,  final String key) {
    HttpHeaders headers =  setAcceptAndContentTypeHeaders();
    HttpEntity< String> entity =  new HttpEntity< String>(PERSON1_AS_JSON, headers);
     try {
      ResponseEntity< String> result = RestClientUtils.getRestTemplate().exchange(
             "http://localhost:8080/geode/v1/People?key=1" , HttpMethod.POST,
            entity,  String.class);

       System.out.println( "STATUS_CODE = " + result.getStatusCode().value());
       System.out.println( "HAS_BODY = " + result.hasBody());
       System.out.println( "LOCATION_HEADER = " + result.getHeaders().getLocation().toString());
    }  catch (HttpClientErrorException e) {
       System.out.println( "Http Client encountered error, msg:: " + e.getMessage());
    }  catch(HttpServerErrorException se) {
       System.out.println( "Server encountered error, msg::" + se.getMessage());
    }  catch (Exception e) {
       System.out.println( "Unexpected ERROR...!!");
    }
  }
}
```

## \#1a. <%=vars.product_name%> Cache Java Client (MyJavaClient.java)

``` pre
package org.apache.geode.javaclient;

 import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Map;

 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.client.ClientCache;
 import org.apache.geode.cache.client.ClientCacheFactory;
 import org.apache.geode.cache.client.ClientRegionFactory;
 import org.apache.geode.cache.client.ClientRegionShortcut;
 import org.apache.geode.domain.Gender;
 import org.apache.geode.domain.Person;
 import org.apache.geode.pdx.PdxInstance;
 import org.apache.geode.util.DateTimeUtils;

 public class MyJavaClient {

   public static void main( String[] args) {
    ClientCacheFactory cf =  new ClientCacheFactory().addPoolServer( "localhost", 40405);
    ClientCache cache = cf.setPdxReadSerialized( true).create();
    ClientRegionFactory rf = cache.createClientRegionFactory(ClientRegionShortcut.PROXY);

    Region region = rf.create( "People");

     //Get data on key "1" , update it and put it again in cache
    Person actualObj =  null;
     Object obj = region.get( "1");
     if(obj  instanceof PdxInstance){
       System.out.println( "Obj is PdxInstance");
      PdxInstance pi = (PdxInstance)obj;
       Object obj2 = pi.getObject();
       if(obj2  instanceof Person){
        actualObj = (Person)obj2;
         System.out.println( "Received Person :" + actualObj.toString());
      } else {
         System.out.println( "Error: obj2 is expected to be of type Person");
      }
    } else {
       System.out.println( "Error: obj is expected to be of type PdxInstance");
    }

     //update the received object and put it in cache
 if(actualObj !=  null){
      actualObj.setFirstName( "Jane_updated");
      actualObj.setLastName( "Doe_updated");
      region.put( "1", actualObj);
    }

     //Add/putAll set of person objects
 final Person person2 =  new Person(102L,  "Sachin",  "Ramesh",  "Tendulkar", DateTimeUtils.createDate(1975, Calendar.DECEMBER, 14), Gender.MALE);
     final Person person3 =  new Person(103L,  "Saurabh",  "Baburav",  "Ganguly", DateTimeUtils.createDate(1972, Calendar.AUGUST, 29), Gender.MALE);
     final Person person4 =  new Person(104L,  "Rahul",  "subrymanyam",  "Dravid", DateTimeUtils.createDate(1979, Calendar.MARCH, 17), Gender.MALE);
     final Person person5 =  new Person(105L,  "Jhulan",  "Chidambaram",  "Goswami", DateTimeUtils.createDate(1983, Calendar.NOVEMBER, 25), Gender.FEMALE);
     final Person person6 =  new Person(101L,  "Rahul",  "Rajiv",  "Gndhi", DateTimeUtils.createDate(1970, Calendar.MAY, 14), Gender.MALE);
     final Person person7 =  new Person(102L,  "Narendra",  "Damodar",  "Modi", DateTimeUtils.createDate(1945, Calendar.DECEMBER, 24), Gender.MALE);
     final Person person8 =  new Person(103L,  "Atal",  "Bihari",  "Vajpayee", DateTimeUtils.createDate(1920, Calendar.AUGUST, 9), Gender.MALE);
     final Person person9 =  new Person(104L,  "Soniya",  "Rajiv",  "Gandhi", DateTimeUtils.createDate(1929, Calendar.MARCH, 27), Gender.FEMALE);
     final Person person10 =  new Person(104L,  "Priyanka",  "Robert",  "Gandhi", DateTimeUtils.createDate(1973, Calendar.APRIL, 15), Gender.FEMALE);
     final Person person11 =  new Person(104L,  "Murali",  "Manohar",  "Joshi", DateTimeUtils.createDate(1923, Calendar.APRIL, 25), Gender.MALE);
     final Person person12 =  new Person(104L,  "Lalkrishna",  "Parmhansh",  "Advani", DateTimeUtils.createDate(1910, Calendar.JANUARY, 01), Gender.MALE);
     final Person person13 =  new Person(104L,  "Shushma",  "kumari",  "Swaraj", DateTimeUtils.createDate(1943, Calendar.AUGUST, 10), Gender.FEMALE);
     final Person person14 =  new Person(104L,  "Arun",  "raman",  "jetly", DateTimeUtils.createDate(1942, Calendar.OCTOBER, 27), Gender.MALE);
     final Person person15 =  new Person(104L,  "Amit",  "kumar",  "shah", DateTimeUtils.createDate(1958, Calendar.DECEMBER, 21), Gender.MALE);
     final Person person16 =  new Person(104L,  "Shila",  "kumari",  "Dixit", DateTimeUtils.createDate(1927, Calendar.FEBRUARY, 15), Gender.FEMALE);

    Map< String,  Object> userMap =  new HashMap< String,  Object>();
    userMap.put( "2", person6);
    userMap.put( "3", person6);
    userMap.put( "4", person6);
    userMap.put( "5", person6);
    userMap.put( "6", person6);
    userMap.put( "7", person7);
    userMap.put( "8", person8);
    userMap.put( "9", person9);
    userMap.put( "10", person10);
    userMap.put( "11", person11);
    userMap.put( "12", person12);
    userMap.put( "13", person13);
    userMap.put( "14", person14);
    userMap.put( "15", person15);
    userMap.put( "16", person16);

     //putAll all person
    region.putAll(userMap);

     System.out.println( "successfully Put set of Person objects into the cache");
  }

}
```

## \#1b. REST Client Utilities (RestClientUtils.java)

``` pre
package org.apache.geode.util;


 import java.net.URI;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import org.springframework.http.converter.ByteArrayHttpMessageConverter;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.StringHttpMessageConverter;
 import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.UriComponentsBuilder;

 public class RestClientUtils {

   public static final String BASE_URL =  "http://192.0.2.0:8080" ;
   public static final String GEODE_REST_API_CONTEXT =  "/geode";
   public static final String GEODE_REST_API_VERSION =  "/v1";
   public static final URI GEODE_REST_API_WEB_SERVICE_URL = URI
      .create(BASE_URL + GEODE_REST_API_CONTEXT + GEODE_REST_API_VERSION);

   public static RestTemplate restTemplate;
   public static RestTemplate getRestTemplate() {
     if (restTemplate ==  null) {
      restTemplate =  new RestTemplate();
       final List<HttpMessageConverter<?>> messageConverters =  new ArrayList<HttpMessageConverter<?>>();

      messageConverters.add( new ByteArrayHttpMessageConverter());
      messageConverters.add( new StringHttpMessageConverter());
      messageConverters.add(createMappingJackson2HttpMessageConverter());

      restTemplate.setMessageConverters(messageConverters);
    }
     return restTemplate;
  }

   public static HttpMessageConverter< Object> createMappingJackson2HttpMessageConverter() {
     final Jackson2ObjectMapperFactoryBean objectMapperFactoryBean =  new Jackson2ObjectMapperFactoryBean();
    objectMapperFactoryBean.setFailOnEmptyBeans( true);
    objectMapperFactoryBean.setIndentOutput( true);
    objectMapperFactoryBean.setDateFormat( new SimpleDateFormat( "MM/dd/yyyy"));
    objectMapperFactoryBean
        .setFeaturesToDisable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    objectMapperFactoryBean
        .setFeaturesToEnable(
            com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_COMMENTS,
            com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES,
            com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    objectMapperFactoryBean.afterPropertiesSet();

     final MappingJackson2HttpMessageConverter httpMessageConverter =  new MappingJackson2HttpMessageConverter();
    httpMessageConverter.setObjectMapper(objectMapperFactoryBean.getObject());
     return httpMessageConverter;
  }

   public static URI toUri( final String... pathSegments) {
     return toUri(GEODE_REST_API_WEB_SERVICE_URL, pathSegments);
  }

   public static URI toUri( final URI baseUrl,  final String... pathSegments) {
     return UriComponentsBuilder.fromUri(baseUrl).pathSegment(pathSegments)
        .build().toUri();
  }
}
```

## \#1c. Date and Time Utilities (DateTimeUtils.java)

``` pre
package org.apache.geode.util;


 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;

/**
 * The DateTimeUtils class is a utility class  for working with dates and times.
 */
@SuppressWarnings( "unused")
 public abstract class DateTimeUtils {

   public static Calendar createCalendar( final int year,  final int month,  final int day) {
     final Calendar dateTime = Calendar.getInstance();
    dateTime.clear();
    dateTime.set(Calendar.YEAR, year);
    dateTime.set(Calendar.MONTH, month);
    dateTime.set(Calendar.DAY_OF_MONTH, day);
     return dateTime;
  }

   public static Date createDate( final int year,  final int month,  final int day) {
     return createCalendar(year, month, day).getTime();
  }

   public static String format( final Date dateTime,  final String formatPattern) {
     return (dateTime !=  null ?  new SimpleDateFormat(formatPattern).format(dateTime) :  null);
  }

}
```

## \#1d. Person Class (Person.java)

``` pre
package org.apache.geode.domain;


 import java.util.Date;

 import org.apache.geode.internal.lang.ObjectUtils;
 import org.apache.geode.pdx.PdxReader;
 import org.apache.geode.pdx.PdxSerializable;
 import org.apache.geode.pdx.PdxWriter;

 import org.apache.geode.util.DateTimeUtils;

/**
 * The Person class is an abstraction modeling a person.
 */

 public class Person  implements PdxSerializable /*ResourceSupport  implements DomainObject< Long>*/  {

   private static final long serialVersionUID = 42108163264l;

   protected static final String DOB_FORMAT_PATTERN =  "MM/dd/yyyy";

   private Long id;

   private Date birthDate;

   private Gender gender;

   private String firstName;
   private String middleName;
   private String lastName;

   public Person() {
  }

   public Person( final Long id) {
     this.id = id;
  }

   public Person( final String firstName,  final String lastName) {
     this.firstName = firstName;
     this.lastName = lastName;
  }

   public Person( final Long id,  final String firstName,  final String middleName,  final String lastName, Date date, Gender gender) {
     this.id = id;
     this.firstName = firstName;
     this.middleName = middleName;
     this.lastName = lastName;
     this.birthDate = date;
     this.gender = gender;
  }

   public Long getId() {
     return id;
  }

   public void setId( final Long id) {
     this.id = id;
  }

   public String getFirstName() {
     return firstName;
  }

   public void setFirstName( final String firstName) {
     this.firstName = firstName;
  }

   public String getLastName() {
     return lastName;
  }

   public void setLastName( final String lastName) {
     this.lastName = lastName;
  }

   public String getMiddleName() {
     return middleName;
  }

   public void setMiddleName( final String middleName) {
     this.middleName = middleName;
  }

   public Date getBirthDate() {
     return birthDate;
  }

   public void setBirthDate( final Date birthDate) {
     this.birthDate = birthDate;
  }

   public Gender getGender() {
     return gender;
  }

   public void setGender( final Gender gender) {
     this.gender = gender;
  }

  @Override
   public boolean equals( final Object obj) {
     if (obj ==  this) {
       return true;
    }

     if (!(obj  instanceof Person)) {
       return false;
    }

     final Person that = (Person) obj;

     return (ObjectUtils.equals( this.getId(), that.getId())
      || (ObjectUtils.equals( this.getBirthDate(), that.getBirthDate())
      && ObjectUtils.equals( this.getLastName(), that.getLastName())
      && ObjectUtils.equals( this.getFirstName(), that.getFirstName())));
  }

  @Override
   public int hashCode() {
     int hashValue = 17;
    hashValue = 37 * hashValue + ObjectUtils.hashCode(getId());
    hashValue = 37 * hashValue + ObjectUtils.hashCode(getBirthDate());
    hashValue = 37 * hashValue + ObjectUtils.hashCode(getLastName());
    hashValue = 37 * hashValue + ObjectUtils.hashCode(getFirstName());
     return hashValue;
  }

  @Override
   public String toString() {
     final StringBuilder buffer =  new StringBuilder( "{ type = ");
    buffer.append(getClass().getName());
    buffer.append( ", id = ").append(getId());
    buffer.append( ", firstName = ").append(getFirstName());
    buffer.append( ", middleName = ").append(getMiddleName());
    buffer.append( ", lastName = ").append(getLastName());
    buffer.append( ", birthDate = ").append(DateTimeUtils.format(getBirthDate(), DOB_FORMAT_PATTERN));
    buffer.append( ", gender = ").append(getGender());
    buffer.append( " }");
     return buffer.toString();
  }

  @Override
   public void fromData(PdxReader pr) {

    id = pr.readLong( "id");
    firstName = pr.readString( "firstName");
    middleName = pr.readString( "middleName");
    lastName = pr.readString( "lastName");
    birthDate = pr.readDate( "birthDate");
    gender = (Gender)pr.readObject( "gender");
  }

  @Override
   public void toData(PdxWriter pw) {
    pw.writeLong( "id", id);
    pw.writeString( "firstName", firstName);
    pw.writeString( "middleName", middleName);
    pw.writeString( "lastName", lastName);
    pw.writeDate( "birthDate", birthDate);
    pw.writeObject( "gender", gender);
  }

}
```

## \#1e. Gender Class (Gender.java)

``` pre
package org.apache.geode.domain;

/**
 * The Gender  enum is a enumeration of genders (sexes).
 */

 public enum Gender {
  FEMALE,
  MALE
}
```

## \#2. Ruby REST Client (restClient.rb)

``` pre
#!/usr/bin/ruby -w

puts "Hello, Ruby!";

# !/usr/bin/env ruby

require 'json'
require 'net/http'

class JsonSerializable

  def to_json
    hash = {}
    hash["@type"] = "org.apache.geode.web.rest.domain.Person"
    self.instance_variables.each do |var|
      if !var.to_s.end_with?("links")
        hash[var.to_s[1..-1]] = self.instance_variable_get var
      end
    end
    hash.to_json
  end

  def from_json! jsonString
    JSON.load(jsonString).each do |var, val|
      if !var.end_with?("type")
        self.instance_variable_set "@".concat(var), val
      end
    end
  end

end

class Person < JsonSerializable

  attr_accessor :id, :firstName, :middleName, :lastName, :birthDate, :gender

  def initialize(id = nil, firstName = nil, middleName = nil, lastName = nil )
    @id = id
    @firstName = firstName
    @middleName = middleName
    @lastName = lastName
    @birthDate = nil
    @gender = nil
  end

  def to_s
    s = "{ type = Person, id = #{@id}"
    s += ", firstName = #{@firstName}"
    s += ", middleName = #{@middleName}"
    s += ", lastName = #{@lastName}"
    s += ", birthDate = #{@birthDate}"
    s += ", gender = #{@gender}"
    s += "}"
  end

end

if __FILE__ == $0
  #p = Person.new(1, "Jon", "T", "Doe")
  #puts p
  #puts p.inspect
  #puts p.to_json

  uri = URI("http://localhost:8080/geode/v1/People/1");

  personJson = Net::HTTP::get(uri);

  # JSON from server
  puts "JSON read from Server for Person with ID 1...\n #{personJson}"

  p = Person.new
  p.from_json! personJson

  # print the Person to standard out
  puts "Person is...\n #{p}"

  p.id = 1
  p.firstName = "Jack"
  p.lastName = "Handy"
  p.gender = "MALE"

  # prints modified Person to standard out
  puts "Person modified is...\n #{p}"

  puts "JSON sent to Server for Person with ID 1...\n #{p.to_json}"

  Net::HTTP.start(uri.hostname, uri.port) do |http|
    putRequest = Net::HTTP::Put.new uri.path, { "Content-Type" => "application/json" }
    putRequest.body = p.to_json
    http.request(putRequest)
  end

end
```

**Output from running the Ruby client:**

``` pre
prompt# ruby restClient.rb
Hello, Ruby!
JSON read from Server for Person with ID 1...
 {
  "@type" : "org.gopivotal.app.domain.Person",
  "id" : 1,
  "firstName" : "Jane_updated",
  "middleName" : "H",
  "lastName" : "Doe_updated",
  "gender" : "MALE",
  "birthDate" : "04/12/1983"
}
Person is...
 { type = Person, id = 1, firstName = Jane_updated, middleName = H, lastName = Doe_updated, birthDate = 04/12/1983, gender = MALE}
Person modified is...
 { type = Person, id = 1, firstName = Jack, middleName = H, lastName = Handy, birthDate = 04/12/1983, gender = MALE}
JSON sent to Server for Person with ID 1...
 {"@type":"org.apache.geode.web.rest.domain.Person","id":1,"firstName":"Jack","middleName":"H","lastName":"Handy","birthDate":"04/12/1983","gender":"MALE"}
```

## \#3. Python REST Client (restClient.py)

This example uses Python 3 and shows the creation and modification of objects. It uses one external library called `requests`, which is nearly ubiquitous and avoids having to use HTTP code.

``` pre
#!/usr/bin/env python3

# This is simple, repetitive and assumes you have created a region called
# "demoRegion".

import sys
import json
import uuid
import requests

REGION = "demoRegion"
BASE_URI = "http://localhost:8080/geode/v1"

headers = {'content-type': 'application/json'}

person = {'type': 'Person',
          'firstName': 'John',
          'middleName': 'Q',
          'lastName': 'Public',
          'birthDate': '1 Jan 1900'}


def resource_uri(res=None, region=REGION):
    if res:
        return "%s/%s/%s" % (BASE_URI, region, res)
    return "%s/%s" % (BASE_URI, region)


print("[*] First, we'll empty out our demo region - DELETE %s" %
      requests.delete(resource_uri()))

r = requests.delete(resource_uri())
r.raise_for_status()

print("[*] Now, we'll create 5 demo objects")

keys = []

for i in range(1, 6):
    key = uuid.uuid1()

    keys.append(key)
    person['uuid'] = str(key)

    print("\t Creating object with key: POST %s" % key)
    r = requests.post(resource_uri(), data=json.dumps(person),
                      params={'key': key},
                      headers=headers)
    r.raise_for_status()

print("[*] List our keys - GET %s" % resource_uri("keys"))

r = requests.get(resource_uri("keys"))
print(r.text)

print("[*] Here's all our data - GET %s" % resource_uri())

r = requests.get(resource_uri())
print(r.text)

print("[*] Now each key one by one")

for key in keys:
    print("Fetching key - GET %s" % resource_uri(res=key))
    r = requests.get(resource_uri(res=key))
    print(r.text)

print("[*] Now grab one, change the first name to 'Jane' and save it")

print("  GET - %s" % resource_uri(res=keys[0]))
r = requests.get(resource_uri(res=keys[0]))
p = json.loads(r.text)
p['firstName'] = 'Jane'
print("  PUT - %s" % resource_uri(res=keys[0]))
r = requests.put(resource_uri(res=keys[0]), data=json.dumps(p),
                 headers=headers)

print("  GET - %s" % resource_uri(res=keys[0]))
r = requests.get(resource_uri(res=keys[0]))
print(r.text)
```
