Gremlin Server Rest API

2,369 views
Skip to first unread message

Madabhattula Rajesh Kumar

unread,
Nov 16, 2015, 8:58:38 AM11/16/15
to Aurelius
Hi,

I'm new to Gremlin Server Rest API. How to retrieve number vertices in a graph using Gremlin Server REST API.

I'm using CASSANDRA as a storage. My Key_SPACE name is : TITAN_DEMO

Regards,
Rajesh

Jason Plurad

unread,
Nov 16, 2015, 9:38:10 AM11/16/15
to Aurelius
Hi Rajesh,


1. If you're starting from the titan-1.0.0-hadoop1.zip, I'd suggest making a copy of conf/gremlin-server/gremlin-server.yaml into conf/rest-gremlin-server.yaml. Also, copy conf/titan-cassandra.properties to conf/gremlin-server/titan-cassandra-server.properties

cp conf/gremlin-server/gremlin-server.yaml conf/rest-gremlin-server.yaml
cp conf
/titan-cassandra.properties conf/gremlin-server/titan-cassandra-server.properties


2. If you're planning to connect to Gremlin Server from something other than localhost, you'll want to update the host with its IP address or 0.0.0.0 in rest-gremlin-server.yaml

host: 0.0.0.0


3. Configure the Gremlin Server for REST instead of WebSockets (refer to the Gremlin Server documentation). In the rest-gremlin-server.yaml, update the channelizer

channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer


4. Configure the Gremlin Server mapping with the Cassandra properties file with your graph configuration

graphs: {
  graph
: conf/gremlin-server/titan-cassandra-server.properties}


5. Update the titan-cassandra-server.properties with your specific Cassandra properties. In particular, you'll want to update the keyspace name and possibly storage.hostname if Cassandra isn't running on localhost.

storage.hostname=127.0.0.1
storage
.cassandra.keyspace=TITAN_DEMO


6. Sending Gremlin to the Gremlin Server configured for REST is the same, regardless of the actual Gremlin query. Do a HTTP POST of a JSON object with a pair { "gremlin": "g.V().count()" } to the Gremlin Server. Here's what it looks like with a curl:

curl -XPOST -Hcontent-type:application/json -d '{"gremlin":"g.V().count()"}' http://localhost:8182


-- Jason

Jason Plurad

unread,
Nov 16, 2015, 9:42:15 AM11/16/15
to Aurelius
And also, be sure to start Gremlin Server with the configuration file

./bin/gremlin-server.sh ./conf/gremlin-server/rest-gremlin-server.yaml

-- Jason

Eric Lubow

unread,
Nov 20, 2015, 10:50:59 AM11/20/15
to Aurelius
I also might recommend (warning, shameless self-plug here) taking a look at the titan-docker-cassandra package I put together: https://hub.docker.com/r/elubow/titan-gremlin/

This is a good way to easily start, destroy, recreate and otherwise toy with Gremlin and Titan in a way that can easily help you learn.

Todd Leo

unread,
Dec 8, 2015, 1:52:36 AM12/8/15
to Aurelius

Hi Jason,

I’m following your steps to start the Gremlin Server REST service, with successfully configured Gremlin Server with HBase storage backend. But I confronted 400 Error when testing REST API with curl:

$ curl -v -XPOST -Hcontent-type:application/json -d '{"gremlin":"g.V().count()"}' http://localhost:8182

* About to connect() to localhost port 8182 (#0)
*   Trying 127.0.0.1... connected
> POST / HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8182
> Accept: */*
> content-type:application/json
> Content-Length: 27
> 
* upload completely sent off: 27out of 27 bytes
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
* no chunk, no close, no size. Assume close to signal end
< 
* Closing connection #0
{"message":"no serializer for requested Accept header: */*"}

also tried other inputs from TK3 Doc, resulting the same error in response. Then I figured may be I should specify the Accept header to Accept: application/json, only to find {"message":"no serializer for requested Accept header: application/json"}.


BR,
Todd Leo

Jason Plurad

unread,
Dec 8, 2015, 10:55:23 AM12/8/15
to Aurelius
Hi Todd,

1. Try passing an explicit Accept header for application/json like this

curl -v -XPOST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"gremlin":"g.V().count()"}' http://localhost:8182

2. Stephen checked in a fix for the accept header processing for */* in July, but it doesn't look like it is in the TinkerPop 3.0.x codebase. Whenever Titan 1.1 with TinkerPop 3.1 comes out, I think this problem will be already fixed.

-- Jason

Todd Leo

unread,
Dec 8, 2015, 9:25:24 PM12/8/15
to Aurelius

Hi Jason,

Thanks for the respond. Sadly, explicit parameter for Accept doesn’t work either:

$ curl -v -XPOST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"gremlin":"g.V().count()"}' http://localhost:8182


{"message":"no serializer for requested Accept header: application/json"}

BR,
Todd Leo

Todd Leo

unread,
Dec 8, 2015, 10:34:34 PM12/8/15
to Aurelius
Hi Jason, 

Now I know where the issue is, after viewing the log from gremlin server. It turns out the `useMapperFromGraph: graph` in Serializer config was left default, with the graph instance name changed in **graphs** settings, and it works as I put the graph instance name correctly. However it leads to another consideration: what if I have multiple graphs configured? Can a serializer use mapper from multiple graphs?

Stephen Mallette

unread,
Dec 9, 2015, 6:09:56 AM12/9/15
to Aurelius
If you have multiple graphs then you have to manually configure the the serializer with the IoRegistries setting.  i'm thinking about suggesting that we deprecate "useMapperFromGraph" - it was the precursor to "ioRegistries" if i remember correctly and I don't think it promotes a good usage pattern.

--
You received this message because you are subscribed to the Google Groups "Aurelius" group.
To unsubscribe from this group and stop receiving emails from it, send an email to aureliusgraph...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/aureliusgraphs/b27ae22c-0f14-4c09-8280-3b241def5410%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

SLiZn Liu

unread,
Dec 10, 2015, 2:45:24 AM12/10/15
to Aurelius

Hi Stephen,

I’m not particularly familiar with the setting of gremlin server. Did you mean using ioRegistries instead of useMapperFromGraph, like the following(imagine I have 2 graphs configured, graph1 and graph2):

serializers:
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { useMapperFromGraph: graph1 }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { useMapperFromGraph: graph2 }}
#...other serializers, GraphSONMessageSerializerGremlinV1d0,  GraphSONMessageSerializerV1d0

and, is this property a requirement for each graph instance? What if I don’t set useMapperFromGraph nor ioRegistries?


BR,
Todd Leo



You received this message because you are subscribed to a topic in the Google Groups "Aurelius" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/aureliusgraphs/v4UcYwE5UVU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to aureliusgraph...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/aureliusgraphs/CAA-H43-0ZeL03K%3DaL3D1k25tW%2B618bgnWCCLHgMUbjDuN3J74w%40mail.gmail.com.

Stephen Mallette

unread,
Dec 11, 2015, 7:27:42 AM12/11/15
to Aurelius
I don't think that what you showed there will be considered a valid configuration.  If both of your graphs are of the same type (i.e. both Titan) then you can largely just pick one of your Titan instances to the value you pass to useMapperFromGraph, because the serializers from one TitanGraph will be the same for another.  If you have two different graphs, then you need to use the ioRegistries config.  If you don't set either, then you will hit serialization errors if you return data from Gremlin Server that isn't serializable (like Titan Vertex identifier).

Kevin I

unread,
Jan 13, 2016, 3:11:51 AM1/13/16
to Aurelius
Hello there,

I read through all the replies above but I face the original problem as the OP.

I am using Titan1.0.0 and when using the REST API, `curl -XPOST -Hcontent-type:application/json -d '{"gremlin":"g.V().count()"}' http://localhost:8182`, I get the following error

{
  "message": "no serializer for requested Accept header: application/json"
}

This is how I started titan:

`sudo ./bin/titan.sh -c conf/freeth.properties start`

Contents of `freeth.properties`:

# Titan configuration sample: Cassandra & Elasticsearch over sockets
#
# This file connects to Cassandra and Elasticsearch services running
# on localhost over the Thrift API and the Elasticsearch native
# "Transport" API on their respective default ports.  The Cassandra
# and Elasticsearch services must already be running before starting
# Titan with this file.

# The primary persistence provider used by Titan.  This is required.  It
# should be set one of Titan's built-in shorthand names for its standard
# storage backends (shorthands: berkeleyje, cassandrathrift, cassandra,
# astyanax, embeddedcassandra, hbase, inmemory) or to the full package and
# classname of a custom/third-party StoreManager implementation.
#
# Default:    (no default value)
# Data Type:  String
# Mutability: LOCAL
storage.backend=cassandrathrift

# The hostname or comma-separated list of hostnames of storage backend
# servers.  This is only applicable to some storage backends, such as
# cassandra and hbase.
#
# Default:    127.0.0.1
# Data Type:  class java.lang.String[]
# Mutability: LOCAL
storage.hostname=127.0.0.1

storage.directory=/home/kevin/databases

#storage.cassandra.keyspace=TITAN_DEMO
# Whether to enable Titan's database-level cache, which is shared across
# all transactions. Enabling this option speeds up traversals by holding
# hot graph elements in memory, but also increases the likelihood of
# reading stale data.  Disabling it forces each transaction to
# independently fetch graph elements from storage before reading/writing
# them.
#
# Default:    false
# Data Type:  Boolean
# Mutability: MASKABLE
cache.db-cache = true

# How long, in milliseconds, database-level cache will keep entries after
# flushing them.  This option is only useful on distributed storage
# backends that are capable of acknowledging writes without necessarily
# making them immediately visible.
#
# Default:    50
# Data Type:  Integer
# Mutability: GLOBAL_OFFLINE
#
# Settings with mutability GLOBAL_OFFLINE are centrally managed in Titan's
# storage backend.  After starting the database for the first time, this
# file's copy of this setting is ignored.  Use Titan's Management System
# to read or modify this value after bootstrapping.

cache.db-cache-clean-wait = 20

# Default expiration time, in milliseconds, for entries in the
# database-level cache. Entries are evicted when they reach this age even
# if the cache has room to spare. Set to 0 to disable expiration (cache
# entries live forever or until memory pressure triggers eviction when set
# to 0).
#
# Default:    10000
# Data Type:  Long
# Mutability: GLOBAL_OFFLINE
#
# Settings with mutability GLOBAL_OFFLINE are centrally managed in Titan's
# storage backend.  After starting the database for the first time, this
# file's copy of this setting is ignored.  Use Titan's Management System
# to read or modify this value after bootstrapping.

cache.db-cache-time = 180000

# Size of Titan's database level cache.  Values between 0 and 1 are
# interpreted as a percentage of VM heap, while larger values are
# interpreted as an absolute size in bytes.
#
# Default:    0.3
# Data Type:  Double
# Mutability: MASKABLE

cache.db-cache-size = 0.25

# Connect to an already-running ES instance on localhost

# The indexing backend used to extend and optimize Titan's query
# functionality. This setting is optional.  Titan can use multiple
# heterogeneous index backends.  Hence, this option can appear more than
# once, so long as the user-defined name between "index" and "backend" is
# unique among appearances.Similar to the storage backend, this should be
# set to one of Titan's built-in shorthand names for its standard index
# backends (shorthands: lucene, elasticsearch, es, solr) or to the full
# package and classname of a custom/third-party IndexProvider
# implementation.
#
# Default:    elasticsearch
# Data Type:  String
# Mutability: GLOBAL_OFFLINE
#
# Settings with mutability GLOBAL_OFFLINE are centrally managed in Titan's
# storage backend.  After starting the database for the first time, this
# file's copy of this setting is ignored.  Use Titan's Management System
# to read or modify this value after bootstrapping.

index.search.backend=elasticsearch

# The hostname or comma-separated list of hostnames of index backend
# servers.  This is only applicable to some index backends, such as
# elasticsearch and solr.
#
# Default:    127.0.0.1
# Data Type:  class java.lang.String[]
# Mutability: MASKABLE

index.search.hostname=127.0.0.1

# The Elasticsearch node.client option is set to this boolean value, and
# the Elasticsearch node.data option is set to the negation of this value.
# True creates a thin client which holds no data.  False creates a regular
# Elasticsearch cluster node that may store data.
#
# Default:    true
# Data Type:  Boolean
# Mutability: GLOBAL_OFFLINE
#
# Settings with mutability GLOBAL_OFFLINE are centrally managed in Titan's
# storage backend.  After starting the database for the first time, this
# file's copy of this setting is ignored.  Use Titan's Management System
# to read or modify this value after bootstrapping.

index.search.elasticsearch.client-only=true

# Or start ES inside the Titan JVM
#index.search.backend=elasticsearch
#index.search.directory=../db/es
#index.search.elasticsearch.client-only=false
#index.search.elasticsearch.local-mode=true

Contents of `gremlin-server/gremlin-server.yaml`

host: localhost
port
: 8182
threadPoolWorker
: 1
gremlinPool
: 8
scriptEvaluationTimeout
: 30000
serializedResponseTimeout
: 30000
#channelizer: org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer
channelizer
: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer
graphs
: {
   
#graph: conf/gremlin-server/titan-berkeleyje-server.properties}
   
#graph: conf/gremlin-server/titan-cassandra-es-server.properties}
    graph
: conf/freeth.properties}
plugins
:
 
- aurelius.titan
scriptEngines
: {
  gremlin
-groovy: {
    imports
: [java.lang.Math],
    staticImports
: [java.lang.Math.PI],
    scripts
: [scripts/empty-sample.groovy]},
  nashorn
: {
      imports
: [java.lang.Math],
      staticImports
: [java.lang.Math.PI]}}

serializers
:
 
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { useMapperFromGraph: graph }}

 
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }}
 
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0, config: { useMapperFromGraph: graph }}
 
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0, config: { useMapperFromGraph: graph }}
processors
:
 
- { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
metrics
: {
  consoleReporter
: {enabled: true, interval: 180000},
  csvReporter
: {enabled: true, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv},
  jmxReporter
: {enabled: true},
  slf4jReporter
: {enabled: true, interval: 180000},
  gangliaReporter
: {enabled: false, interval: 180000, addressingMode: MULTICAST},
  graphiteReporter
: {enabled: false, interval: 180000}}
threadPoolBoss
: 1
maxInitialLineLength
: 4096
maxHeaderSize
: 8192
maxChunkSize
: 8192
maxContentLength
: 65536
maxAccumulationBufferComponents
: 1024
resultIterationBatchSize
: 64
writeBufferHighWaterMark
: 32768
writeBufferHighWaterMark
: 65536
ssl
: {
  enabled
: false}

The database is working however through the gremlin console. Also, the REST API works when the storage backend in BerkeleyDB. This is tested in another machine too and its the same there. Any idea what the problem is?

Pressy Fdo

unread,
Jan 13, 2016, 7:13:07 AM1/13/16
to Aurelius
Try adding,

gremlin.graph=com.thinkaurelius.titan.core.TitanFactory

in the configuration file. It solved the problem for me.
...

Kevin I

unread,
Jan 13, 2016, 7:16:50 AM1/13/16
to Aurelius
@Pressy

Thanks a lot. It works now!
Reply all
Reply to author
Forward
0 new messages