Giter Club home page Giter Club logo

anormcypher's Introduction

AnormCypher

Table of Contents

Join the chat at https://gitter.im/AnormCypher/AnormCypher This is a Neo4j client library for the HTTP Cypher transactional endpoints.

The goals of this library are to provide a great API to use Cypher, and it will be modeled after Anorm from Play, which I found to be pleasant to use with SQL. More info about Anorm can be found here: http://www.playframework.org/documentation/2.0.4/ScalaAnorm

Integration tests currently run against neo4j-community-2.1.3.

Build Status

The latest release is 0.10.0. Version 0.10.x depends on play-json and play-ws libraries from Play 2.5.3. For Play 2.4.x, please use version 0.9.1. If you need to use AnormCypher in Play 2.3.x, please use version 0.7.0.

AnormCypher did not support transaction before 0.9. The last release without transaction support is 0.8.1.

As of version 0.5, AnormCypher uses play-json and Scala 2.11.

If you want to use scala 2.10, you need to use version 0.4.x (latest is 0.4.4)

If you want to use scala 2.9, you need to use version 0.3.x (latest is 0.3.1).

SBT Console Demo

Install neo4j on localhost. For neo4j servers after 2.3, disable authentication by editing the following line in conf/neo4j-server.properties before running neo4j start

dbms.security.auth_enabled=false

If you would like to connect to a neo4j instance on another server, or use authentication, simply set the appropriate parameters (host, port, username, and password, etc) in the Neo4jREST factory method in the following example.

Clone the AnormCypher repository from github, and run sbt test:console

Alternatively, you can create a build.sbt file with the following:

scalaVersion := "2.11.8"

resolvers ++= Seq(
  "anormcypher" at "http://repo.anormcypher.org/",
  "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases/"
)


libraryDependencies ++= Seq(
  "org.anormcypher" %% "anormcypher" % "0.10.0"
)

[Note] If you take the second step route from above, you will notice that the async http client ships with the default logging level set to DEBUG. To reduce the noise from logging, you can use the logback-test.xml configuration in our src/test/resources. If you want to see the details of the http client, you can simply run sbt console which won't include test-classes on the classpath.

Assuming you have a local Neo4j Server running on the default port, try (note: this will create nodes on your database):

import org.anormcypher._
import play.api.libs.ws._

// Provide an instance of WSClient
val wsclient = ning.NingWSClient()

// Setup the Rest Client
// Need to add the Neo4jConnection type annotation so that the default
// Neo4jConnection -> Neo4jTransaction conversion is in the implicit scope
implicit val connection: Neo4jConnection = Neo4jREST()(wsclient)

// Provide an ExecutionContext
implicit val ec = scala.concurrent.ExecutionContext.global

// create some test nodes
Cypher("""create (anorm:anormcyphertest {name:"AnormCypher"}), (test:anormcyphertest {name:"Test"})""").execute()

// a simple query
val req = Cypher("match (n:anormcyphertest) return n.name")

// get a stream of results back
val stream = req()

// get the results and put them into a list
stream.map(row => {row[String]("n.name")}).toList

// remove the test nodes
Cypher("match (n:anormcyphertest) delete n")()

// shut down WSClient
wsclient.close()

Usage

You'll probably notice that this usage is very close to Play's Anorm. That is the idea!

Configuring a server

The default is localhost, but you can specify a special server when your app is starting via the setServer or setURL options.

import org.anormcypher._
import play.api.libs.ws._

// Provide an instance of WSClient
implicit val wsclient = ning.NingWSClient()

// without auth
implicit val connection: Neo4jConnection = Neo4jREST("localhost", 7474)

// or with basic auth
implicit val connection2: Neo4jConnection = Neo4jREST("localhost", 7474, "username", "password")

Executing Cypher Queries

To start you need to learn how to execute Cypher queries.

First, import org.anormcypher._, setup an implicit Neo4jREST instance, and then use the Cypher object to create queries.

import org.anormcypher._ 
import play.api.libs.ws._

// Provide an instance of WSClient
implicit val wsclient = ning.NingWSClient()
implicit val connection: Neo4jConnection = Neo4jREST()

val result: Boolean = Cypher("START n=node(0) RETURN n").execute()

The execute() method returns a Boolean value indicating whether the execution was successful.

Since Scala supports multi-line strings, feel free to use them for complex Cypher statements:

// create some sample data
val result = Cypher("""
  create (germany {name:"Germany", population:81726000, type:"Country", code:"DEU"}),
         (france {name:"France", population:65436552, type:"Country", code:"FRA", indepYear:1790}),
         (monaco {name:"Monaco", population:32000, type:"Country", code:"MCO"});
  """).execute()
// result: Boolean = true
 
val cypherQuery = Cypher(
  """
    start n=node(*) 
    match n-->m
    where n.code = 'FRA'
    return n,m;
  """
)

If your Cypher query needs dynamic parameters, you can declare placeholders like {name} in the query string, and later assign a value to them with on:

Cypher(
  """
    start n=node(*) 
    where n.type = "Country"
      and n.code = {countryCode}
    return n.name
  """
).on("countryCode" -> "FRA")

Retrieving data with CypherStatement.apply()

The first way to access the results of a return query is to use statement.apply() or simply statement()

When you call apply() on any Cypher statement, you will receive a Seq of CypherRow instances, where each row can be seen as a dictionary:

// Create Cypher query
val allCountries = Cypher("start n=node(*) where n.type = 'Country' return n.code as code, n.name as name")
 
// Transform the resulting Seq[CypherRow] to a List[(String,String)]
val countries = allCountries.apply().map(row => 
  row[String]("code") -> row[String]("name")
).toList

In the following example we will count the number of Country entries in the database, so the result set will be a single row with a single column:

// First retrieve the first row
val firstRow = Cypher("start n=node(*) where n.type = 'Country' return count(n) as c").apply().head
 
// Next get the content of the 'c' column as Long
val countryCount = firstRow[Long]("c")
// countryCount: Long = 3

Reactive Streaming with Neo4jConnection.streamAutocommit

Occasionally we need to handle a very large data set returned from the Neo4j server -- a dataset so large that it would exhaust the JVM's heap space if the entire server response were read in before being processed. There might be situations where we cannot avoid loading the entire data set; in such cases the only solution would be increasing the maximum heap size and running the program on a machine with more memory. However, most of the time, processing could start without having the complete data set. For example, if all we have to do is to perform some transformation on each CypherResultRow and then stream the data to the client, there is no reason to wait till we have received all the data from the server; we can use reactive streaming to start working as soon as we receive one CypherResultRow.

AnormCypher uses Play's Enumerator|Iteratee API to achieve reactive streaming. Specifically, the Neo4jConnection trait defines the streamAutocommit method with the following signature:

import play.api.libs.iteratee._

trait Neo4jConnection {
  ...
  def streamAutocommit(stmt: CypherStatement)(implicit ec: ExecutionContext): Enumerator[CypherResultRow]
  ...
}

while another method, execute, consumes the reactive stream (Enumerator[CypherResultRow]) produced by this method and returns the entire response as a Sequence, asynchronously

trait Neo4jConnection {
  /** Asynchronous, non-streaming query */
  def execute(stmt: CypherStatement)(implicit ec: ExecutionContext): Future[Seq[CypherResultRow]] =
      streamAutocommit(stmt) |>>> Iteratee.getChunks[CypherResultRow]
}

As the method name implies, the query is executed in its own separate transaction, because the large data set it's designed to work with prohibits the transaction to be held open across requests. (We will talk about transaction a little bit later)

One obvious gain is that, if you are using Play for the web front end, and Neo4j as the data store, you can now stream cypher result sets directly to the browsing client using AnomrCypher as a bridge.

object MyController extends Controller {
  def allNodes: Enumerator[CypherResultRow] = neo4jconn.streamAutocommit(CypherStatement("match n return n"))

  def stream = Action {
	  Ok.chunked(allNodes map (_.toString))
  }

  import akka.stream.scaladsl.Source
  import play.api.libs.streams.Streams
  def akkaStream = Action {
    Ok.chunked(Source(Streams.enumeratorToPublisher(allNodes map (_.toString))))
  }
}

Consult James Roper's article for a good introduction to Enumerator and Iteratee and to the problems they are designed to solve.

Transaction API

AnormCypher supports transactional cypher with the Neo4jTransaction.withTx method. The method is a standard Loan Pattern implementation, starting a new transaction before passing the transction to the code block, then either commiting the transaction if the code executed successfully or rolling back the transaction if an exception is throw during code execution. A typical use of the API is as follows:

val Tag = "anormcyphertest"
val res = Neo4jTransaction.withTx { implicit tx =>
      val res1 = Cypher(s"""create (n:${Tag}{name: "n1", level: 1}) return n.name as name, n.level as level """)()
//      res1(0)[String]("name") shouldBe "n1"

      val res2 = Cypher(s"""create (n:${Tag}{name: "n2", level: 2}) return n.name as name""")()
//      res2(0)[String]("name") shouldBe "n2"

      val res3 = Cypher(s"""match (n1:${Tag}{name: "n1"}), (n2:${Tag}{name: "n2"})
create (n1)-[r:hasChildren]->(n2)""")()
    }
Await.result(res, 3.seconds)

One important to remember is that, within the code block passed to withTx, the CypherStatements should all execute sequentially. This is best ensured by calling apply() on each statement. It is possible to use results from previous statements within the same transaction.

Using Pattern Matching

You can also use Pattern Matching to match and extract the CypherRow content. In this case the column name doesn’t matter. Only the order and the type of the parameters is used to match.

The following example transforms each row to the correct Scala type:

case class SmallCountry(name:String) 
case class BigCountry(name:String) 
case class France()

// NOTE: case CypherRow syntax is NOT YET SUPPORTED
val countries = Cypher("start n=node(*) where n.type = 'Country' return n.name as name, n.population as pop")().collect {
  case CypherRow("France", _) => France()
  case CypherRow(name:String, pop:Int) if(pop > 1000000) => BigCountry(name)
  case CypherRow(name:String, _) => SmallCountry(name)      
}
// countries: Seq[Product with Serializable] = List(BigCountry(Germany), France(), SmallCountry(Monaco))

Note that since collect(…) ignores the cases where the partial function isn’t defined, it allows your code to safely ignore rows that you don’t expect.

Special data types

Nodes

Nodes can be extracted as so:

// NOTE: case CypherRow syntax is NOT YET SUPPORTED
Cypher("start n=node(*) where n.type = 'Country' return n.name as name, n")().map {
  case CypherRow(name: String, n: org.anormcypher.NeoNode) => name -> n
}

Here we specifically chose to use map, as we want an exception if the row isn’t in the format we expect.

A Node is just a simple Scala case class, not quite as type-safe as configuring your own:

case class NeoNode(props:Map[String,Any])

Relationships

Relationships can be extracted as so:

// NOTE: case CypherRow syntax is NOT YET SUPPORTED
Cypher("start n=node(*) match n-[r]-m where has(n.name) return n.name as name, r;")().map {
  case CypherRow(name: String, r: org.anormcypher.NeoRelationship) => name -> r
}

Here we specifically chose to use map, as we want an exception if the row isn’t in the format we expect.

Similarly, a Relationship is just a simple Scala case class, not quite as type-safe as configuring your own:

case class NeoRelationship(props:Map[String,Any])

Dealing with Nullable columns

If a column can contain Null values in the database schema, you need to manipulate it as an Option type.

For example, the indepYear of the Country table is nullable, so you need to match it as Option[Int]:

// NOTE: case CypherRow syntax is NOT YET SUPPORTED
Cypher("start n=node(*) where n.type = 'Country' return n.name as name, n.indepYear as year;")().collect {
  case CypherRow(name:String, Some(year:Int)) => name -> year
}

If you try to match this column as Int it won’t be able to parse Null values. Suppose you try to retrieve the column content as Int directly from the dictionary:

Cypher("start n=node(*) where n.type = 'Country' return n.name as name, n.indepYear as indepYear;")().map { row =>
  row[String]("name") -> row[Int]("indepYear")
}

This will produce an UnexpectedNullableFound(COUNTRY.INDEPYEAR) exception if it encounters a null value, so you need to map it properly to an Option[Int], as:

Cypher("start n=node(*) where n.type = 'Country' return n.name as name, n.indepYear as indepYear;")().map { row =>
  row[String]("name") -> row[Option[Int]]("indepYear")
}

This is also true for the parser API, as we will see next.

Using the Parser API (the Parser API is a work in progress)

You can use the parser API to create generic and reusable parsers that can parse the result of any Cypher query.

Note: This is really useful, since most queries in a web application will return similar data sets. For example, if you have defined a parser able to parse a Country from a result set, and another Language parser, you can then easily compose them to parse both Country and Language from a single return.

First you need to import org.anormcypher.CypherParser._

First you need a CypherRowParser, i.e. a parser able to parse one row to a Scala value. For example we can define a parser to transform a single column result set row, to a Scala Long:

val rowParser = scalar[Long]

Then we have to transform it into a CypherResultSetParser. Here we will create a parser that parse a single row:

val rsParser = scalar[Long].single

So this parser will parse a result set to return a Long. It is useful to parse to results produced by a simple Cypher count query:

val count: Long = Cypher("start n=node(*) return count(n)").as(scalar[Long].single)

Let’s write a more complicated parser:

str("name") ~ int("population"), will create a CypherRowParser able to parse a row containing a String name column and an Integer population column. Then we can create a ResultSetParser that will parse as many rows of this kind as it can, using *:

val populations:List[String~Int] = {
  Cypher("start n=node(*) where n.type = 'Country' return n.*").as( str("n.name") ~ int("n.population") * ) 
}

As you see, this query’s result type is List[String~Int] - a list of country name and population items.

You can also rewrite the same code as:

val result:List[String~Int] = {
  Cypher("start n=node(*) where n.type = 'Country' return n.*").as(get[String]("n.name")~get[Int]("n.population")*) 
}

Now what about the String~Int type? This is an AnormCypher type that is not really convenient to use outside of your database access code. You would rather have a simple tuple (String, Int) instead. You can use the map function on a CypherRowParser to transform its result to a more convenient type:

str("n.name") ~ int("n.population") map { case n~p => (n,p) }

Note: We created a tuple (String,Int) here, but there is nothing stopping you from transforming the CypherRowParser result to any other type, such as a custom case class.

Now, because transforming A~B~C types to (A,B,C) is a common task, we provide a flatten function that does exactly that. So you finally write:

val result:List[(String,Int)] = {
  Cypher("start n=node(*) where n.type = 'Country' return n.*").as(
    str("n.name") ~ int("n.population") map(flatten) *
  ) 
}

Now let’s try with a more complicated example. How to parse the result of the following query to retrieve the country name and all spoken languages for a country code?

start country=node_auto_index(code="FRA")
match country-[:speaks]->language
return country.name, language.name;

Let's start by parsing all rows as a List[(String,String)] (a list of name,language tuples):

var p: CypherResultSetParser[List[(String,String)] = {
  str("country.name") ~ str("language.name") map(flatten) *
}

Now we get this kind of result:

List(
  ("France", "Arabic"), 
  ("France", "French"), 
  ("France", "Italian"), 
  ("France", "Portuguese"), 
  ("France", "Spanish"), 
  ("France", "Turkish")
)

We can then use the Scala collection API, to transform it to the expected result:

case class SpokenLanguages(country:String, languages:Seq[String])

languages.headOption.map { f =>
  SpokenLanguages(f._1, languages.map(_._2))
}

Finally, we get this convenient function:

case class SpokenLanguages(country:String, languages:Seq[String])

def spokenLanguages(countryCode: String): Option[SpokenLanguages] = {
  val languages: List[(String, String)] = Cypher(
    """
      start country=node_auto_index(code="{code}")
      match country-[:speaks]->language
      return country.name, language.name;
    """
  )
  .on("code" -> countryCode)
  .as(str("country.name") ~ str("language.name") map(flatten) *)

  languages.headOption.map { f =>
    SpokenLanguages(f._1, languages.map(_._2))
  }
}

To continue, let’s complicate our example to separate the official language from the others:

case class SpokenLanguages(
  country:String, 
  officialLanguage: Option[String], 
  otherLanguages:Seq[String]
)

def spokenLanguages(countryCode: String): Option[SpokenLanguages] = {
  val languages: List[(String, String, Boolean)] = Cypher(
    """
      start country=node_auto_index(code="{code}")
      match country-[:speaks]->language
      return country.name, language.name, language.isOfficial;
    """
  )
  .on("code" -> countryCode)
  .as {
    str("country.name") ~ str("language.name") ~ str("language.isOfficial") map {
      case n~l~"T" => (n,l,true)
      case n~l~"F" => (n,l,false)
    } *
  }

  languages.headOption.map { f =>
    SpokenLanguages(
      f._1, 
      languages.find(_._3).map(_._2),
      languages.filterNot(_._3).map(_._2)
    )
  }
}

If you try this on the world sample database, you will get:

$ spokenLanguages("FRA")
> Some(
    SpokenLanguages(France,Some(French),List(
      Arabic, Italian, Portuguese, Spanish, Turkish
    ))
)

Contributors

Thanks

  • The Play Framework team for providing the Anorm library, the basis for this library. (and now the play-json module)
  • Databinder.net, for the Dispatch library
  • Neo Technologies for Neo4j!

License LGPL

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/

anormcypher's People

Contributors

freeeve avatar gitter-badger avatar jasonjackson avatar johnmurray avatar kai-chen avatar martinstuder avatar mdlsr avatar okumin avatar sirocchj avatar zarthross avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

anormcypher's Issues

A list of maps as a param

I've been trying to send a list of objects, somewhat like this:

Cypher("foreach (o in {objects} | ... )")
  .on("objects" -> List(
    Map("a" -> "b", "c" -> "d"), 
    Map("a" -> "b", "c" -> "d"),
    ...
  )

As far as I can see there are no json Writes available from Seq[Map[String, Any]]. I'm not sure where to add this, but I believe writes in Neo4jRest.scala should contain an extra case statement for this case(list of maps).

However, this functionality is available in the Neo4j Rest API. See Creating multiple nodes with properties. I've also got it to work making the REST request on my own.

I've been able to work around this by moving the foreach into the scala code:

val objects = List(Map("a" -> "b", "c" -> "d"), Map("a" -> "b", "c" -> "d"))
for(o <- objects) {
  Cypher("...").on("object" -> o)
}

But I think we can all see that Cypher is reconstructing the execution path for the query each time, which is not very efficient.

I'm holding off on writing a pull request for this because I'm not too well versed in Play's JSON library to make the proper Writes change, but I hope that this can be fixed soon. It seems to me to be a pretty glaring missing feature.

Neo4jREST.mapFormat doesn't support JsNull values

I'm seeing the "unsupported type" exception when mapFormat encounters a JsNull value.

implicit val mapFormat = new Format[Map[String, Any]] {
    def read(xs: Seq[(String, JsValue)]): Map[String, Any] = (xs map {
      ...
      case (k, JsNull) => k -> null
      ...
}

Exception in maven project

Exception in thread "main" java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
    at org.anormcypher.Neo4jREST.<init>(Neo4jREST.scala:14)
    at org.anormcypher.Neo4jREST$.apply(Neo4jREST.scala:56)
    at TagML$.<init>(TagML.scala:26)
    at TagML$.<clinit>(TagML.scala)
    at TagML.main(TagML.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:665)
    at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:170)
    at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:193)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:112)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

And here is my code

import scala.collection.JavaConverters._
import org.ansj.splitWord.analysis.NlpAnalysis
import org.ansj.splitWord.analysis.ToAnalysis
import org.apache.hadoop.hbase.client._
import org.apache.hadoop.hbase.{HBaseConfiguration, HTableDescriptor, TableName}
import org.apache.hadoop.hbase.filter.PageFilter
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp
import org.apache.hadoop.hbase.mapreduce.TableInputFormat
import org.apache.hadoop.hbase.protobuf.ProtobufUtil
import org.apache.hadoop.hbase.util.{Base64, Bytes}
import com.feheadline.com.backend.recommend.util.Env
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd._
import org.apache.spark.mllib.feature.{Word2Vec, Word2VecModel}
import org.anormcypher._

object TagML {
//.....
//exception here
  implicit val connection = Neo4jREST(
        "tree",
        7474,
       "/db/data/"
      )
//......

}

AnormCypherSpec.afterEach() doesn't work for Neo4j 2.x

While implementing some own code dealing with Scala and Neo4j based on AnormCypher, I found a possible issue in your test code. After testing the method afterEach() should clean up the database from test nodes and edges with

MATCH (n) OPTIONAL MATCH (n)-[r]-() WHERE n.tag = "anormcyphertest" DELETE n, r

But that deletes nothing in Neo4j 2.0.3. In version 2.1.2 of Neo4j it yet will delete all nodes and edges from database, not only the tagged ones.

In Neo4j 2.x works the following Cypher statement:

MATCH (n { tag: "anormcyphertest" } ) OPTIONAL MATCH (n)-[r]-() DELETE n, r

Cannot query data with neo4j 3.2.1

New to this project. When I try this code:
`

val query = Cypher(
  """
    |MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(tomHanksMovies) RETURN tom,tomHanksMovies
  """.stripMargin
)

val rs  = query.apply.map(row=>
  row[String]("tom") -> row[String]("tomHanksMovies")
)
println(rs)

`

I got the following exception:

Exception in thread "main" java.lang.RuntimeException: Expected '[' but got '"' / chr(34)
at scala.sys.package$.error(package.scala:27)
at play.api.libs.iteratee.Iteratee$$anonfun$run$1.apply(Iteratee.scala:396)
at play.api.libs.iteratee.Iteratee$$anonfun$run$1.apply(Iteratee.scala:389)
at play.api.libs.iteratee.StepIteratee$$anonfun$fold$2.apply(Iteratee.scala:706)
at play.api.libs.iteratee.StepIteratee$$anonfun$fold$2.apply(Iteratee.scala:706)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:120)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
at scala.concurrent.Promise$class.complete(Promise.scala:55)
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23)
at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:121)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

Any help on getting started with it will be greatly appreciated. Thanks!

NoSuchMethodError with Play 2.5

The following code produces error:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import org.anormcypher.Neo4jREST
import play.api.libs.json.Json
import play.api.libs.ws.ning

object importTraces extends App {
  implicit val system = ActorSystem("neo4j-system")
  implicit val materializer = ActorMaterializer()
  implicit val wsclient = ning.NingWSClient()
  implicit val connection = Neo4jREST("localhost", 7474, "/db/data/", "guest", "neo4j")
}
Exception in thread "main" java.lang.NoSuchMethodError: play.api.libs.functional.syntax.package$.functionalCanBuildApplicative(Lplay/api/libs/functional/Applicative;)Lplay/api/libs/functional/FunctionalCanBuild;
    at org.anormcypher.Neo4jREST$.<init>(Neo4jREST.scala:141)
    at org.anormcypher.Neo4jREST$.<clinit>(Neo4jREST.scala)
    at importTraces$.delayedEndpoint$importTraces$1(importTraces.scala:12)
    at importTraces$delayedInit$body.apply(importTraces.scala:7)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at importTraces$.main(importTraces.scala:7)
    at importTraces.main(importTraces.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

i use

"com.typesafe.play" % "play-ws_2.11" % "2.5.0"
"org.anormcypher" %% "anormcypher" % "0.8.1"

Nullable isn't working

scala> Cypher("start n=node(*) where n.type! = 'Country' return n.name as name, n.indepYear? as indepYear;")().map { row =>
     |   row[String]("name") -> row[Option[Int]]("indepYear")
     | }
<console>:12: error: could not find implicit value for parameter c: org.anormcypher.Column[Option[Int]]
                row[String]("name") -> row[Option[Int]]("indepYear")

placeholder doesn't work

i created a simple test : and the placeholder strings are not replaced and end up with {email} , {name} , {password} in the database

def create(user: User): User = {
Cypher(
"""
CREATE (n:User { email : " {email} ", name : "{name}", password : "{password}" })
""")
.on("email" -> user.email, "name" -> user.name, "password" -> user.password)
.execute()
user
}

Intellij 14 Project

Hi

Hope someone might be using intellij as their IDE and may spot what I am doing wrong.
Steps followed to create project:
I have
created a new folder,
added build.sbt (see screen shot for contents),
ran sbt console from command line,
started intellij 14, imported project following instructions from here(https://confluence.jetbrains.com/display/IntelliJIDEA/Getting+Started+with+SBT).

When I create a class based on the sample code on (http://www.anormcypher.org/) I get a "cannot resolve method Nes4jREST.apply", also looking at the AnormCypher.scala source, Intellij is displaying a lot of syntax error indicators.

The image shows the project layout (have tried with java 1.7 same issues) and the contents of key files

Thanks in advance.

image

after running a cypher query, the jvm can't exit

(master branch)
Seems like a thread stays alive:

val req = Cypher("MATCH (people:Person) RETURN people.name LIMIT 10")
val stream = req()

I can't find a "close()" or "shutdown()" method. Is there one?

Thread dump:

"DestroyJavaVM" #24 prio=5 os_prio=0 tid=0x00007f5f1c011000 nid=0x6680 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"ForkJoinPool-1-worker-3" #23 daemon prio=5 os_prio=0 tid=0x00007f5e90001800 nid=0x66b0 waiting on condition [0x00007f5f019a4000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076eba7618> (a scala.concurrent.forkjoin.ForkJoinPool)
at scala.concurrent.forkjoin.ForkJoinPool.scan(ForkJoinPool.java:2075)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

"Hashed wheel timer #1" #19 prio=5 os_prio=0 tid=0x00007f5ebc001000 nid=0x66ae waiting on condition [0x00007f5f01ba6000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.jboss.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:483)
at org.jboss.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:392)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at java.lang.Thread.run(Thread.java:745)

"Hashed wheel timer #2" #21 prio=5 os_prio=0 tid=0x00007f5f1cccb000 nid=0x66ad waiting on condition [0x00007f5f01ea7000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at org.jboss.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:483)
at org.jboss.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:392)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at java.lang.Thread.run(Thread.java:745)

"New I/O boss #9" #20 prio=5 os_prio=0 tid=0x00007f5f1cccf000 nid=0x66ab runnable [0x00007f5f01fa8000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076e642488> (a sun.nio.ch.Util$2)
- locked <0x000000076e642478> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076e642360> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #8" #18 daemon prio=5 os_prio=0 tid=0x00007f5f1cbc0000 nid=0x66a8 runnable [0x00007f5f020a9000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df754d0> (a sun.nio.ch.Util$2)
- locked <0x000000076df754c0> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df753a8> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #7" #17 daemon prio=5 os_prio=0 tid=0x00007f5f1cbd1800 nid=0x66a7 runnable [0x00007f5f021aa000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df73b88> (a sun.nio.ch.Util$2)
- locked <0x000000076df73b78> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df73a60> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #6" #16 daemon prio=5 os_prio=0 tid=0x00007f5f1cbcf800 nid=0x66a6 runnable [0x00007f5f022aa000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df72290> (a sun.nio.ch.Util$2)
- locked <0x000000076df72280> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df72168> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #5" #15 daemon prio=5 os_prio=0 tid=0x00007f5f1cbce000 nid=0x66a5 runnable [0x00007f5f023ab000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df70998> (a sun.nio.ch.Util$2)
- locked <0x000000076df70988> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df70870> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #4" #14 daemon prio=5 os_prio=0 tid=0x00007f5f1cbef000 nid=0x66a4 runnable [0x00007f5f024ad000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df6f0a0> (a sun.nio.ch.Util$2)
- locked <0x000000076df6f090> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df6ef78> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #3" #13 daemon prio=5 os_prio=0 tid=0x00007f5f1cbf2000 nid=0x66a3 runnable [0x00007f5f025ae000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df6d778> (a sun.nio.ch.Util$2)
- locked <0x000000076df6d768> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df6d650> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #2" #12 daemon prio=5 os_prio=0 tid=0x00007f5f1cbcb000 nid=0x66a1 runnable [0x00007f5f026af000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076df6be80> (a sun.nio.ch.Util$2)
- locked <0x000000076df6be70> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076df6bd58> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"New I/O worker #1" #11 daemon prio=5 os_prio=0 tid=0x00007f5f1cbca000 nid=0x669e runnable [0x00007f5f027b0000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x000000076de8f720> (a sun.nio.ch.Util$2)
- locked <0x000000076de8f698> (a java.util.Collections$UnmodifiableSet)
- locked <0x000000076de8e340> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

"Monitor Ctrl-Break" #9 daemon prio=5 os_prio=0 tid=0x00007f5f1c89b800 nid=0x669b runnable [0x00007f5f03105000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x00000007702768c8> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x00000007702768c8> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:93)
at java.lang.Thread.run(Thread.java:745)

"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f5f1c0c9800 nid=0x6699 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f5f1c0c4800 nid=0x6698 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f5f1c0c2800 nid=0x6697 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f5f1c0bf800 nid=0x6696 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f5f1c0be000 nid=0x6695 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f5f1c086000 nid=0x668e in Object.wait() [0x00007f5f088df000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000770e88bb0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x0000000770e88bb0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f5f1c084000 nid=0x668c in Object.wait() [0x00007f5f089e0000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000770e905e0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
- locked <0x0000000770e905e0> (a java.lang.ref.Reference$Lock)

Exception running any Cypher query

Hey,
I'm trying to run a simple Cypher Query, but keep getting a RuntimeException with no message.

The cypher REST endpoint is running and anormCypher is pointing to the right address:

scala> Neo4jREST.baseURL
res19: String = http://localhost:7474/db/data

And the query is simple

Cypher("MATCH (n) RETURN n")()

When I run it from a running Play! 2.2.1 application, I get the following error:

    at org.anormcypher.Neo4jREST$.sendQuery(Neo4jREST.scala:138) ~[anormcypher_2.10-0.4.4.jar:0.4.4]
    at org.anormcypher.CypherStatement.apply(AnormCypher.scala:342) ~[anormcypher_2.10-0.4.4.jar:0.4.4]
    at services.graph.Neo4jGraphRepository.getRelationship(GraphService.scala:47) ~[classes/:na]
    at services.graph.GraphService.getRelationship(GraphService.scala:13) ~[classes/:na]
    at controllers.GraphController$$anonfun$getRelationship$1.apply(GraphController.scala:25) ~[classes/:na]
    at controllers.GraphController$$anonfun$getRelationship$1.apply(GraphController.scala:25) ~[classes/:na]
    at play.api.mvc.ActionBuilder$$anonfun$apply$11.apply(Action.scala:255) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.ActionBuilder$$anonfun$apply$11.apply(Action.scala:255) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:221) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.ActionBuilder$$anonfun$apply$10.apply(Action.scala:220) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$.invokeBlock(Action.scala:357) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:309) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:109) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.utils.Threads$.withContextClassLoader(Threads.scala:18) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:108) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:107) ~[play_2.10-2.2.1.jar:2.2.1]
    at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:107) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:100) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:481) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:517) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$13.apply(Iteratee.scala:493) ~[play-iteratees_2.10-2.2.1.jar:2.2.1]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [scala-library.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [scala-library.jar:na]
    ... 6 common frames omitted

From REPL I get:

play.api.Application$$anon$1: Execution exception[[RuntimeException: ]]
    at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10-2.2.1.jar:2.2.1]
    at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10-2.2.1.jar:2.2.1]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:165) [play_2.10-2.2.1.jar:2.2.1]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:162) [play_2.10-2.2.1.jar:2.2.1]
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33) [scala-library.jar:na]
    at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185) [scala-library.jar:na]
    at scala.util.Try$.apply(Try.scala:161) [scala-library.jar:na]
    at scala.util.Failure.recover(Try.scala:185) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:387) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$recover$1.apply(Future.scala:387) [scala-library.jar:na]
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:29) [scala-library.jar:na]
    at play.api.libs.iteratee.Execution$$anon$1.execute(Execution.scala:43) [play-iteratees_2.10-2.2.1.jar:2.2.1]
    at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:37) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:133) [scala-library.jar:na]
    at scala.concurrent.Promise$class.complete(Promise.scala:55) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:58) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$flatMap$1$$anonfun$apply$3.apply(Future.scala:278) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$flatMap$1$$anonfun$apply$3.apply(Future.scala:278) [scala-library.jar:na]
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:29) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.processBatch$1(Future.scala:731) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply$mcV$sp(Future.scala:746) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply(Future.scala:723) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$Batch$$anonfun$run$1.apply(Future.scala:723) [scala-library.jar:na]
    at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$Batch.run(Future.scala:722) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$.scala$concurrent$Future$InternalCallbackExecutor$$unbatchedExecute(Future.scala:782) [scala-library.jar:na]
    at scala.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:773) [scala-library.jar:na]
    at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:37) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:133) [scala-library.jar:na]
    at scala.concurrent.Promise$class.complete(Promise.scala:55) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:58) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:274) [scala-library.jar:na]
    at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:274) [scala-library.jar:na]
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:29) [scala-library.jar:na]
    at play.api.libs.iteratee.Execution$$anon$2.execute(Execution.scala:70) [play-iteratees_2.10-2.2.1.jar:2.2.1]
    at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:37) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:133) [scala-library.jar:na]
    at scala.concurrent.Promise$class.complete(Promise.scala:55) [scala-library.jar:na]
    at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:58) [scala-library.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23) [scala-library.jar:na]
    at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42) [akka-actor_2.10-2.2.0.jar:2.2.0]
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) [akka-actor_2.10-2.2.0.jar:2.2.0]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library.jar:na]

And finally, the travis build shows the following error:

[error] /home/travis/build/AnormCypher/AnormCypher/src/main/scala/org/anormcypher/http/neo4jhttp.scala:45: type mismatch;
[error]  found   : play.api.libs.iteratee.Enumeratee[Array[Char],Any]
[error]  required: play.api.libs.iteratee.Iteratee[Array[Char],?]
[error]       jsObject(
[error]               ^
[error] /home/travis/build/AnormCypher/AnormCypher/src/main/scala/org/anormcypher/http/neo4jhttp.scala:59: type mismatch;
[error]  found   : play.api.libs.iteratee.Enumerator[Array[Byte]]
[error]  required: play.api.libs.iteratee.Enumerator[org.anormcypher.CypherRow]
[error]       Enumerator.fromStream(stream)(bodyParser)
[error]                                    ^
[error] two errors found
[error] (compile:compile) Compilation failed
[error] Total time: 62 s, completed Dec 30, 2013 4:01:12 PM

Does this sounds like a version issue or did I entirely miss a configuration step?

Parse result as Float

It seems that Java float is supported, but Scala Float is not.

Scala Double is supported though.

Query performance regressions since v0.7.1

I recently attempted to upgrade an application from 0.7.1 (with Play 2.4) to 0.10.0 (with Play 2.5). I noticed that a particular operation involving approximately 500 queries against Neo4J was taking about 6 times longer with the newer version.

After spending some time investigating, it seems that there was a slowdown between version 0.7.1 and 0.8.1 (introduction of Enumerators) and between 0.8.1 and 0.9.1 (introduction of transactions).

Given the obvious difficulties of replicating exactly what I was seeing with my real-world data, I have created a very simple app that repeatedly queries a simple data set 10,000 times. The example is of course contrived, but running it with different versions of AnormCypher seems to reflect the levels of performance differences I was seeing with real world data.

Data set:
`
CREATE (a:Certificate) set a.name='G'

CREATE (b:Certificate) set b.name='Not Rated'

CREATE (c:Certificate) set c.name='U'

CREATE (d:Certificate) set d.name='PG'

CREATE (e:Certificate) set e.name='PG-13'

CREATE (f:Certificate) set f.name='12'

CREATE (g:Certificate) set g.name='12A'

CREATE (h:Certificate) set h.name='15'

CREATE (i:Certificate) set i.name='15A'

CREATE (j:Certificate) set j.name='16'

CREATE (k:Certificate) set k.name='18'

CREATE (l:Certificate) set l.name='R'

CREATE (m:Certificate) set m.name='R18'

CREATE (n:Certificate) set n.name='NC-17'

`

Code
`

val wsClient = NingWSClient(NingWSClientConfig())

// implicit val neoClient = new Neo4jREST(wsClient, "localhost", 7474, "neo4j", "neo4j", false) // 0.9.1

implicit val neoClient = new Neo4jREST(wsClient, "localhost", 7474, "/db/data/", "neo4j", "neo4j")

implicit val ec = scala.concurrent.ExecutionContext.global


val before = ZonedDateTime.now()

Await.result(Future.sequence((1 to 10000).map { _ =>
  Cypher(
    "MATCH (c: Certificate) RETURN c.name"
  ).async()
}).map(_.flatten), Duration.Inf)

val after = ZonedDateTime.now()

println((after.toInstant.toEpochMilli - before.toInstant.toEpochMilli) / 1000 + " seconds")

`

The results, using Play 2.4 dependencies in all cases were:
0.7.1 3 seconds
0.8.1 7 seconds
0.9.1 12 seconds

This is blocking my ability to upgrade to Play 2.5. If it's not easy to improve the performance with transactions/enumerators, perhaps an option would be to add an extra method that doesn't use these features?

Relationships/Nodes aren't being parsed properly

Cypher("start n=node(*) return n.name as name, n")().map {
     case CypherRow(name: String, n: org.anormcypher.NeoNode) => name -> n
}

fails with an exception:

scala.MatchError: Row('ColumnName(name,None)':AnormCypher as String, 'ColumnName(n,None)':{outgoing_relationships=http://localhost:7474/db/data/node/1144/relationships/out, data={name=AnormCypher}, traverse=http://localhost:7474/db/data/node/1144/traverse/{returnType}, all_typed_relationships=http://localhost:7474/db/data/node/1144/relationships/all/{-list|&|types}, property=http://localhost:7474/db/data/node/1144/properties/{key}, self=http://localhost:7474/db/data/node/1144, properties=http://localhost:7474/db/data/node/1144/properties, outgoing_typed_relationships=http://localhost:7474/db/data/node/1144/relationships/out/{-list|&|types}, incoming_relationships=http://localhost:7474/db/data/node/1144/relationships/in, extensions={}, create_relationship=http://localhost:7474/db/data/node/1144/relationships, paged_traverse=http://localhost:7474/db/data/node/1144/paged/traverse/{returnType}{?pageSize,leaseTime}, all_relationships=http://localhost:7474/db/data/node/1144/relationships/all, incoming_typed_relationships=http://localhost:7474/db/data/node/1144/relationships/in/{-list|&|types}} as String) (of class org.anormcypher.CypherResultRow)
    at $anonfun$1.apply(<console>:11)
    at $anonfun$1.apply(<console>:11)
    at scala.collection.immutable.Stream.map(Stream.scala:175)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:914)
    at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:546)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:577)
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:543)
    at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:694)
    at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:745)
    at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:712)
    at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:745)
    at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:712)
    at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:745)
    at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:651)
    at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:542)
    at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:550)
    at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822)
    at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:851)
    at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:57)
    at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:48)
    at sbt.Console.console0$1(Console.scala:23)
    at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
    at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
    at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)

Support neo4j 2.2

Hi do you plan on supporting 2.2 ? there is need for authentication support for exemple.

Upload latest version to maven repository

Hello,

I am really interested in using Async support introduced in 37342c9 to use AnormCypher as a non blocking driver.
The 0.6.0 version does not include async support.

Any chance you could upload it to your maven repository ?

Add Play 2.5 support

It seems AnormCypher doesn't work with Play 2.5,

I got this error while compiling Play:
Error:(12, 35) could not find implicit value for parameter materializer: akka.stream.Materializer val wsclient = ning.NingWSClient() ^

can't find play 2.2-snapshot dependency

I tried to examples using scala 2.10 and play 2.1.1.
when I run "console" in play, I met message such as below.

[error] (*:update) sbt.ResolveException: unresolved dependency: play#play-json_2.10;2.2-SNAPSHOT: not found

should I set SNAPSHOT repository ?

Placeholder replacement only works after the WHERE syntax

I want to create a generic query with a custom label (tag) and a custom relationship. This piece of code does not work. AnormCypher only parse the {userId} placeholder.

val socialTag = "social"
val relationship = "KNOWS"
val id = 123
val req: CypherStatement = Cypher( """ MATCH (a:{tag})-[:`{relationship}`]->(b) WHERE a.id={userId} RETURN a.id """)
          .on("tag" -> socialTag)
          .on("relationship" -> relationship)
          .on("userId" -> id)

Regards,
Gabriel.

With Neo4j 3.0.x, Cypher query returning 2 results per record (one with actual value, one with null)

Hi,

Thanks for implementing this library. I am still very new to neo4j.

When i tried out the code example from the docs (as mentioned below), I got UnExpectedNullableException. I managed to figure out why. Each record in the result set is duplicated (one with actual value, one with null). I tried with 0.8.1 version and it works as expected. Here is the code I used:

Code below return duplicate row at v0.9.0

import org.anormcypher._
  import play.api.libs.ws._

  val wsclient = ning.NingWSClient()
  implicit val connection = Neo4jREST()(wsclient)
  implicit val ec = scala.concurrent.ExecutionContext.global

  Cypher("""create (anorm:anormcyphertest {name:"AnormCypher"})""").execute()
  val req = Cypher("match (n:anormcyphertest) return n.name")
  val stream = req()
  stream.foreach(row => {
    println(row[String]("n.name"))
  })
  Cypher("match (n:anormcyphertest) delete n")()
  wsclient.close()

Cheers

RowParser not working with Cypher's collect(prop)

Hey guys,
I'm trying to run a query that returns a collect() aggregate (http://docs.neo4j.org/chunked/stable/query-aggregation.html#aggregation-collect)
Kind of like this:

MATCH (n:Person)
RETURN id(n) as id, collect(n.property) as collectProperty

AnormCypher seems to return a mutable.ListBuffer for the collectProperty, and I'm not sure if the library doesn't yet support this type of return or if I'm parsing the CypherRow incorrectly.
I've tried both pattern matching (not supported I understand) and the brute force approach as well.

Pattern matching:
Doesn't work because everything is interpreted as a string?

case CypherRow(id: Long, collectProperty: scala.collection.mutable.ListBuffer[String] 
//Throws in runtime
[MatchError: CypherResultRow('id':35 as String, 'collectProperty':ListBuffer() as String) (of class org.anormcypher.CypherResultRow)]

And brute force doesn't work either because there's no implicit converter for collections.

Result(row[Long]("id"), row[scala.collection.mutable.ListBuffer[String]]("collectProperty"))

//Does not compile because:
could not find implicit value for parameter c: org.anormcypher.Column[scala.collection.mutable.ListBuffer[String]]

Any thoughts on how to solve this?

modularize the backend

Is there anyway you could modularize the backend? I would like to use this for some embedded database work as well and use the same API as for using remote connections. I often use the embedded version with some direct traversals but for many cypher queries, there is nothing special about them and being able to use this library for either embedded or remote databases would help with re-use.

Provide mechanism to convert to case classes more easily than .map

Right now you can do:

case class MyCaseClass(n:String, a:Int)

Cypher("start n=node(1) return n.name, n.age")().map(row =>
  MyCaseClass(row[String]("n.name"), row[Int]("n.age")))
// returns Stream[MyCaseClass]

I'd rather make something like:

Cypher("start n=node(1) return n.name, n.age")().as[MyCaseClass]
// returns Stream[MyCaseClass]

Play 2.4.x

Hi, I think there may be a compatibility issue with play 2.4. Using AnormCypher 6.0 I got this stack trace:

java.lang.NoSuchMethodError: com.ning.http.client.AsyncHttpClientConfig$Builder.setRequestTimeoutInMs(I)Lcom/ning/http/client/AsyncHttpClientConfig$Builder;
    at dispatch.InternalDefaults$BasicDefaults$.builder(defaults.scala:45)
    at dispatch.InternalDefaults$.client(defaults.scala:32)
    at dispatch.Http$.<init>(execution.scala:30)
    at dispatch.Http$.<clinit>(execution.scala)
    at org.anormcypher.Neo4jREST.sendQuery(Neo4jREST.scala:34)
    at org.anormcypher.CypherStatement.apply(AnormCypher.scala:361)
    at models.daos.UserDAOImpl.find(UserDAOImpl.scala:43)
    at models.services.UserServiceImpl.save(UserServiceImpl.scala:46)
    at controllers.SocialAuthController$$anonfun$authenticate$1$$anonfun$apply$2$$anonfun$apply$3.apply(SocialAuthController.scala:48)
    at controllers.SocialAuthController$$anonfun$authenticate$1$$anonfun$apply$2$$anonfun$apply$3.apply(SocialAuthController.scala:47)
    at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251)
    at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:249)
    at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
    at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
    at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:91)
    at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
    at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
    at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
    at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:90)
    at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

.as Isn't working

Not defined...

scala> val populations:List[String~Int] = {
     |   Cypher("start n=node(*) where n.type! = 'Country' return n.*").as( str("n.name") ~ int("n.population") * )
     | }
<console>:11: error: value as is not a member of org.anormcypher.CypherStatement
         Cypher("start n=node(*) where n.type! = 'Country' return n.*").as( str("n.name") ~ int("n.population") * )

Unable to access repo.anormcypher.org

Hi,
Please reassign if this is not the right place. I'm trying to download anormcypher packages via SBT. Unfortunately, I'm not able to connect to repo.anormcypher.org (infact www.anormcypher.org is not accessible). Looks like the domain name got expired on 13th Nov 2015.
Any clues on how to get it back? Is there any alternative repo that I can use? Please let us know.

Exact URL that I'm trying: http://repo.anormcypher.org/org/anormcypher/anormcypher_2.11/0.6.0/anormcypher_2.11-0.6.0.pom

Async transaction support

It would be nice if the transaction API would support async transactions. I'm thinking about something like this:

def withAsyncTx[A](code: Neo4jTransaction => Future[A])(implicit conn: Neo4jConnection, ec: ExecutionContext): Future[A] =
    (for {
      tx <- conn.beginTx
      r <- code(tx)
    } yield {
      tx.commit
      r
    }) recover {
      case e: ControlThrowable => tx.commit; throw e
      case e: Throwable =>      tx.rollback; throw e
    }

This would allow things like:

Neo4jTransaction.withAsyncTx { implicit tx =>
  for {
    r1 <- cypherStmt1.async()
    r2 <- cypherStmt2(...).async()
   ...
  } yield ...
}

Generating Dynamic CQL in AnormCypher

Hi,

I would like to understand does the existing functionalities of cypher supports the option of generate dynamic CQL for the CRUD operations i.e., it should perform all the operations using the object mapping without using any of low level CQL.

Please let me know if you need more details on my problem statement.

neo4j-jdbc

Not really an issue, more of a comment. I ran across this (newish) project https://github.com/neo4j-contrib/neo4j-jdbc - from some basic testing it looks like anorm/Hikari/neo4j-jdbc works just fine.

SQL"""create (tim:twoname {fname:"Tim", lname:"Foo"}), (katie:twoname {fname:"Katie", lname:"Bar"})""".execute
val names = SQL"""match (n:twoname) return n.fname, n.lname""".as(Macro.indexedParser[NameClass].*).map(_.fname)

Is there anything I should be aware of that AnormCypher does that neo4j-jdbc will not be able to handle?

Authentication with username and password.

Looking at the source code of dispatch, seems it's not difficult to implement.

credentials = new Credentials(username,password)
...
...
val result = Http(cypherRequest OK as.String, credentials).either

New to scala, don't be mad if it doesn't work:-)

Keep up the good work!

A number of the tests are failing with an exception

After following the instructions in the README.md file:

BELL-MBP-SWHITE:/Users/swhite/projects/AnormCypher> sbt test
[info] Loading project definition from /Users/swhite/projects/AnormCypher/project
[info] Set current project to AnormCypher (in build file:/Users/swhite/projects/AnormCypher/)
[info] Compiling 1 Scala source to /Users/swhite/projects/AnormCypher/target/scala-2.11/test-classes...
[info] AnormCypherAsyncSpec:
[info] Cypher
[info] Exception encountered when attempting to run a suite with class name: org.anormcypher.async.AnormCypherAsyncSpec *** ABORTED ***
[info] java.lang.RuntimeException: Expected '[' but got '"' / chr(34)
[info] at scala.sys.package$.error(package.scala:27)
[info] at play.api.libs.iteratee.Iteratee$$anonfun$run$1.apply(Iteratee.scala:396)
[info] at play.api.libs.iteratee.Iteratee$$anonfun$run$1.apply(Iteratee.scala:389)
[info] at play.api.libs.iteratee.StepIteratee$$anonfun$fold$2.apply(Iteratee.scala:706)
[info] at play.api.libs.iteratee.StepIteratee$$anonfun$fold$2.apply(Iteratee.scala:706)
[info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
[info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
[info] at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:120)
[info] at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71)
[info] at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)

...

[info] ...
[info] Run completed in 3 seconds, 465 milliseconds.
[info] Total number of tests run: 13
[info] Suites: completed 2, aborted 7
[info] Tests: succeeded 13, failed 0, canceled 0, ignored 0, pending 0
[info] *** 7 SUITES ABORTED ***
[error] Error during tests:
[error] org.anormcypher.async.Neo4jRESTAsyncSpec
[error] org.anormcypher.async.AnormCypherAsyncSpec
[error] org.anormcypher.CypherParserSpec
[error] org.anormcypher.AnormCypherSpec
[error] org.anormcypher.Neo4jTransactionSpec
[error] org.anormcypher.Neo4jRESTSpec
[error] org.anormcypher.async.CypherParserAsyncSpec
error sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 11 s, completed May 27, 2016 8:08:26 AM
BELL-MBP-SWHITE:/Users/swhite/projects/AnormCypher>

AnormCypher fails resolving dependencies

If I try to install AnormCypher after cloning it from GitHub by calling sbt, the resolving of dependencies fails, because http://repo.lessis.me and http://repo.codahale.com are dead. The following changes in the plugin.sbt file work:

resolvers ++= Seq(
  "less is" at "http://repository.jetbrains.com",
//   "coda" at "http://repo.codahale.com",
  "Sonatype" at "http://oss.sonatype.org/content/repositories/releases/")

addSbtPlugin("me.lessis" % "ls-sbt" % "0.1.2")

//addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1")

It seems that building AnormCypher works without "coda". Furthermore, current IDEA versions have a excellent sbt support coming with the Scala plugin, thus maybe

addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1")

could be removed too.

initialCommands in console

I follow below steps and get error.

  1. I uncommented the part in build for "initialCommands in console"
  2. sbt clean compile
  3. sbt console

I get below error. Any help highly appreciated
"[info]
:16: error: could not find implicit value for parameter materializer: akka.stream.Materializer
val wsclient = ning.NingWSClient()
^
:19: error: not enough arguments for method apply: (implicit wsclient: play.api.libs.ws.WSClient, implicit materializer: akka.stream.Materializer)org.anormcypher.Neo4jREST in object Neo4jREST.
Unspecified value parameter materializer.
implicit val connection: Neo4jConnection = Neo4jREST()(wsclient)
^
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).
Type in expressions for evaluation. Or try :help."

How to convert a CypherResultRow into case class

Hi,

I'm totally new to Scala and I'm using this library in combination with Play.
In order to render a template in Play easily, I would like to convert a CypherResultRow into a case class.
Say, you run a query like

val query = Cypher("MATCH (p:Person{name:{name}}) return p.name, p.age")
.on("name->"Karl")

and you define the respective case class like:
case class Person (name: String, age: Int)

How can I convert the result into a List of Person class instances?

I tried the pattern matching mechanism. However, every data type seems to be a String, so pattern matching is not successful as soon as there is another data type besides String.

It would be great, if someone could give me a an example on how this works.

Provide options for caching?

This is kind of a question. Usually this should be done outside of a framework like this, but it might be nice to have some sort of built-in support.

version differences

Need a better way to document between versions... this is becoming a real project!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.