Search This Blog

Friday 26 September 2014

Pivotal GemFire 8 - Starting a Locator / Server directly from IntelliJ 13.x

With the introduction of Pivotal GemFire 8 developers can easily incorporate starting/stopping GemFire Locators/Servers directly within Java code allowing them to easily integrate GemFire  management within their IDE. This ensures developers can develop/test/run GemFire applications all within their IDE of choice making them much more productive using very simple Launcher API's

The locator is a Pivotal GemFire process that tells new, connecting members where running members are located and provides load balancing for server use. A GemFire server is a Pivotal GemFire process that runs as a long-lived, configurable member of a distributed system. The GemFire server is used primarily for hosting long-lived data regions and for running standard GemFire processes such as the server in a client/server configuration.

In this post I am going to show how we can use the following classes to launch a Pivotal GemFire  locator / server from code directly within IntelliJ IDEA allowing you to develop/test GemFire applications directly from your IDE of choice.

Note: In this post we use Intellij IDEA 13.x

com.gemstone.gemfire.distributed.LocatorLauncher API
com.gemstone.gemfire.distributed.ServerLauncher API

1. Add the GemFire 8 maven REPO to your project to ensure we pull the required JAR files.
  
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>gemfire-compression</groupId>
    <artifactId>gemfire-compression</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <gemfire.version>8.0.0</gemfire.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.gemstone.gemfire</groupId>
            <artifactId>gemfire</artifactId>
            <version>${gemfire.version}</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>gemstone-release</id>
            <name>GemStone Maven RELEASE Repository</name>
            <url>http://dist.gemstone.com.s3.amazonaws.com/maven/release</url>
        </repository>
    </repositories>
</project>

2. Create a class as follows to start a locator
  
package pivotal.gemfire.compression;

import com.gemstone.gemfire.distributed.LocatorLauncher;

import java.util.concurrent.TimeUnit;

public class StartLocator
{
    public static void main(String[] args)
    {
        LocatorLauncher locatorLauncher  = new LocatorLauncher.Builder()
                .set("jmx-manager", "true")
                .set("jmx-manager-start", "true")
                .set("jmx-manager-http-port", "8083")
                .set("jmx-manager-ssl", "false")
                .setMemberName("locator")
                .setPort(10334)
                .setBindAddress("localhost")
                .build();

        System.out.println("Attempting to start Locator");

        locatorLauncher.start();

        locatorLauncher.waitOnStatusResponse(30, 5, TimeUnit.SECONDS);

        System.out.println("Locator successfully started");
    }

} 

3. Create a class as follow to start a single cache server, could create as many iof these as you need
  
package pivotal.gemfire.compression;

import com.gemstone.gemfire.distributed.ServerLauncher;

public class StartMember
{
    public static void main(String[] args){
        ServerLauncher serverLauncher  = new ServerLauncher.Builder()
                .setMemberName("server1")
                .set("locators","localhost[10334]")
                .set("cache-xml-file", "cache.xml")
                .set("log-level", "info")
                .build();

        System.out.println("Attempting to start cache server");

        serverLauncher.start();

        System.out.println("Cache server successfully started");
    }
} 

4. Create a cache.xml with a dummy region
  
<!DOCTYPE cache PUBLIC
        "-//GemStone Systems, Inc.//GemFire Declarative Caching 8.0//EN"
        "http://www.gemstone.com/dtd/cache8_0.dtd">
<cache>
    <cache-server bind-address="localhost" port="0" hostname-for-clients="localhost"/>

    <region name="CompressedRegion">
        <region-attributes data-policy="partition">
            <key-constraint>java.lang.String</key-constraint>
            <value-constraint>java.lang.String</value-constraint>
            <partition-attributes redundant-copies="1" total-num-buckets="113"/>
            <eviction-attributes>
                <lru-heap-percentage action="overflow-to-disk"/>
            </eviction-attributes>
        </region-attributes>
    </region>


    <resource-manager critical-heap-percentage="75" eviction-heap-percentage="65"/>

</cache>

5. Edit the run configurations for StartLocator.java to include GEMFIRE env variable as shown below.


6. Run StartLocator.java as shown below.


7. Run StartMember.java as shown below.


8. Finally from the IDE run a script called verify.sh to view the cluster member/regions to ensure it worked.

verify.sh
  
#!/bin/bash

. ./setup.sh

gfsh <<EOF
connect --locator=localhost[10334];
list members;
list regions;
exit;
EOF  

Output



More Information

Pivotal GemFire Locator Processes
http://gemfire.docs.pivotal.io/latest/userguide/deploying/topics/running_the_locator.html

Pivotal GemFire Server Processes
http://gemfire.docs.pivotal.io/latest/userguide/deploying/topics/running_the_cacheserver.html

Thursday 11 September 2014

Creating a Pivotal GemFireXD Data Source Connection from IntelliJ IDEA 13.x

In order to create a Pivotal GemFireXD Data Source Connection from IntelliJ 13.x , follow the steps below. You will need to define a GemFireXD driver , prior to creating the Data Source itself.

1. Bring up the Databases panel.

2. Define a GemFireXD Driver as follows


3. Once defined select it by using the following options. Your using the Driver you created at #2 above

+ -> Data Source -> com.pivotal.gemfirexd.jdbc.ClientDriver 

4. Create a Connection as shown below. You would need to having a running GemFireXD cluster at this point in order to connect.



5.  Once connected you can browse objects as shown below.



6. Finally we can run DML/DDL directly from IntelliJ as shown below.


Thursday 4 September 2014

Variable in list with Postgres JDBC and Greenplum

I previously blogged on how to create a variable JDBC IN list with Oracle. Here is how you would do it with Pivotal Greenplum. Much easier , without having to write a function. In the Greenplum demo below we use the any function combined with string_to_array

http://theblasfrompas.blogspot.com.au/2008/02/variable-in-list-with-oracle-jdbc-and.html

Code as follows
  
import java.sql.*;
import java.sql.DriverManager;

/**
 * Created by papicella on 4/09/2014.
 */
public class VariableInListGreenplum
{

    public VariableInListGreenplum()
    {
    }

    private Connection getConnection() throws SQLException, ClassNotFoundException
    {
        Class.forName("org.postgresql.Driver");
        Connection conn = null;
        conn = DriverManager.getConnection(
                "jdbc:postgresql://127.0.0.1:5432/apples","pas", "pas");

        return conn;
    }

    public void run() throws SQLException
    {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rset = null;
        String queryInList =
                        "SELECT DEPTNO, " +
                        "       DNAME, " +
                        "       LOC " +
                        "FROM   scott.DEPT " +
                        "WHERE DEPTNO = any(string_to_array(?,', ')) ";

        try
        {
            conn = getConnection();
            stmt = conn.prepareStatement(queryInList);
            stmt.setString(1, "10, 20, 30");
            rset = stmt.executeQuery();

            while (rset.next())
            {
                System.out.println("Dept [" + rset.getInt(1) + ", " +
                                              rset.getString(2) + "]");
            }
        }
        catch (Exception e)
        {
            System.out.println("Exception occurred");
            e.printStackTrace();
        }
        finally
        {
            if (conn != null)
            {
                conn.close();
            }

            if (stmt != null)
            {
                stmt.close();
            }

            if (rset != null)
            {
                rset.close();
            }
        }
    }

    public static void main(String[] args) throws Exception
    {
        VariableInListGreenplum test = new VariableInListGreenplum();
        test.run();
    }
}

Wednesday 3 September 2014

REST with Pivotal GemFire 8.0

Pivotal GemFire 8.0 now includes REST support. You can read more about it as follows

http://gemfire.docs.pivotal.io/latest/userguide/gemfire_rest/book_intro.html#concept_7628F498DB534A2D8A99748F5DA5DC94

Here is how we set it up and some quick examples showing how it works with some Region data
In the example below I have PDX setup for the cache servers as shown below.
  
<!DOCTYPE cache PUBLIC
"-//GemStone Systems, Inc.//GemFire Declarative Caching 8.0//EN"
"http://www.gemstone.com/dtd/cache8_0.dtd">
<cache>
    <pdx read-serialized="true">
        <pdx-serializer>
            <class-name>com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer</class-name>
            <parameter name="classes">
                <string>org\.pivotal\.pas\.beans\..*</string>
            </parameter>
        </pdx-serializer>
    </pdx>

.....

1. Firstly you need to enable the REST on a cache server node as shown below. Basically set gemfire.start-dev-rest-api to TRUE , you could use a gemfire.properties file but here we just pass it to GFSH as part of the server start command.

start server --name=server1 --classpath=$CLASSPATH --server-port=40411 --cache-xml-file=./server1/cache.xml --properties-file=./server1/gemfire.properties --locators=localhost[10334] --dir=server1 --initial-heap=1g --max-heap=1g --J=-Dgemfire.http-service-port=7070 --J=-Dgemfire.http-service-bind-address=localhost --J=-Dgemfire.start-dev-rest-api=true

2. Once started we can quickly ensure we have the REST server up on port 7070 as shown below.

[Wed Sep 03 12:39:18 papicella@:~/ant-demos/gemfire/80/demo ] $ netstat -an | grep 7070
tcp4       0      0  127.0.0.1.7070         *.*                    LISTEN

3. Next test that you can access the REST server. The command below will list all the regions available in the cluster.

[Wed Sep 03 12:52:44 papicella@:~/ant-demos/gemfire/80/demo/rest ] $ curl -i http://localhost:7070/gemfire-api/v1
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Location: http://localhost:7070/gemfire-api/v1
Accept-Charset: big5, big5-hkscs, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-compound_text, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp
Content-Type: application/json
Content-Length: 493
Date: Wed, 03 Sep 2014 02:52:46 GMT

{
  "regions" : [ {
    "name" : "demoRegion",
    "type" : "PARTITION",
    "key-constraint" : null,
    "value-constraint" : null
  }, {
    "name" : "departments",
    "type" : "PARTITION",
    "key-constraint" : null,
    "value-constraint" : null
  }, {
    "name" : "employees",
    "type" : "PARTITION",
    "key-constraint" : null,
    "value-constraint" : null
  }, {
    "name" : "complex",
    "type" : "PARTITION",
    "key-constraint" : null,
    "value-constraint" : null
  } ]

4. We have a couple of regions in this cluster and once again I am using the classic DEPT/EMP regions here. Some simple REST command belows on the "/departments" region

View all DEPARTMENT region entries

[Wed Sep 03 12:53:38 papicella@:~/ant-demos/gemfire/80/demo/rest ] $ curl -i http://localhost:7070/gemfire-api/v1/departments
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Location: http://localhost:7070/gemfire-api/v1/departments/20,10,30,40
Content-Type: application/json
Content-Length: 225
Date: Wed, 03 Sep 2014 02:53:40 GMT

{
  "departments" : [ {
    "deptno" : 20,
    "name" : "RESEARCH"
  }, {
    "deptno" : 10,
    "name" : "ACCOUNTING"
  }, {
    "deptno" : 30,
    "name" : "SALES"
  }, {
    "deptno" : 40,
    "name" : "OPERATIONS"
  } ]
}

VIEW a single region entry by KEY

[Wed Sep 03 12:55:34 papicella@:~/ant-demos/gemfire/80/demo/rest ] $ curl -i http://localhost:7070/gemfire-api/v1/departments/10
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Location: http://localhost:7070/gemfire-api/v1/departments/10
Content-Type: application/json
Content-Length: 44
Date: Wed, 03 Sep 2014 02:55:36 GMT

{
  "deptno" : 10,
  "name" : "ACCOUNTING"
}

VIEW multiple entries by KEY

[Wed Sep 03 12:56:25 papicella@:~/ant-demos/gemfire/80/demo/rest ] $ curl -i http://localhost:7070/gemfire-api/v1/departments/10,30
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Location: http://localhost:7070/gemfire-api/v1/departments/10,30
Content-Type: application/json
Content-Length: 123
Date: Wed, 03 Sep 2014 02:56:28 GMT

{
  "departments" : [ {
    "deptno" : 10,
    "name" : "ACCOUNTING"
  }, {
    "deptno" : 30,
    "name" : "SALES"
  } ]
}

5. We can even use the Spring REST shell as shown below.

Obtain rest-shell using the link below.

https://github.com/spring-projects/rest-shell

  
[Wed Sep 03 13:06:22 papicella@:~ ] $ rest-shell

 ___ ___  __ _____  __  _  _     _ _  __
| _ \ __/' _/_   _/' _/| || |   / / | \ \
| v / _|`._`. | | `._`.| >< |  / / /   > >
|_|_\___|___/ |_| |___/|_||_| |_/_/   /_/
1.2.1.RELEASE

Welcome to the REST shell. For assistance hit TAB or type "help".
http://localhost:8080:> baseUri http://localhost:7070/
Base URI set to 'http://localhost:7070'
http://localhost:7070:> follow gemfire-api
http://localhost:7070/gemfire-api:> follow v1
http://localhost:7070/gemfire-api/v1:> follow departments
http://localhost:7070/gemfire-api/v1/departments:> get 20
> GET http://localhost:7070/gemfire-api/v1/departments/20

< 200 OK
< Server: Apache-Coyote/1.1
< Content-Location: http://localhost:7070/gemfire-api/v1/departments/20
< Content-Type: application/json
< Content-Length: 42
< Date: Wed, 03 Sep 2014 03:07:17 GMT
<
{
  "deptno" : 20,
  "name" : "RESEARCH"
}
http://localhost:7070/gemfire-api/v1/departments:>

6. Open a browser and enter the following URL to browse the Swagger-enabled REST APIs:

http://localhost:7070/gemfire-api/docs/index.html



7. Perform an operation as shown below.