Skip to content

Commit

Permalink
support neo4j driver for jooby
Browse files Browse the repository at this point in the history
  • Loading branch information
sbcd90 committed May 25, 2017
1 parent 48b4ec2 commit 91c0231
Show file tree
Hide file tree
Showing 9 changed files with 1,235 additions and 0 deletions.
105 changes: 105 additions & 0 deletions jooby-neo4j/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<parent>
<groupId>org.jooby</groupId>
<artifactId>jooby-project</artifactId>
<version>1.1.1</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>jooby-neo4j</artifactId>

<name>neo4j module</name>

<build>
<plugins>
<!-- sure-fire -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Feature.java</include>
<include>**/Issue*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Jooby -->
<dependency>
<groupId>org.jooby</groupId>
<artifactId>jooby</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Neo4j -->
<dependency>
<groupId>net.iot-solutions.graphdb</groupId>
<artifactId>jcypher</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>com.graphaware.neo4j</groupId>
<artifactId>expire</artifactId>
<version>3.1.4.49.4</version>
</dependency>
<dependency>
<groupId>com.graphaware.neo4j</groupId>
<artifactId>runtime</artifactId>
<version>3.1.4.49</version>
</dependency>

<!-- Test Dependencies -->
<dependency>
<groupId>org.jooby</groupId>
<artifactId>jooby</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jooby</groupId>
<artifactId>jooby-netty</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>

</project>
241 changes: 241 additions & 0 deletions jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4j.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jooby.neo4j;

import com.google.inject.Binder;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigValue;
import iot.jcypher.database.DBAccessFactory;
import iot.jcypher.database.DBProperties;
import iot.jcypher.database.DBType;
import iot.jcypher.database.remote.BoltDBAccess;
import org.jooby.Env;
import org.jooby.Env.ServiceKey;
import org.jooby.Jooby;

import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.Objects.requireNonNull;
import static java.util.Objects.nonNull;
import static com.google.common.base.Preconditions.checkArgument;

/**
* Exposes {@link BoltDBAccess}.
*
* <h1>usage</h1>
*
* <p>
* application.conf:
* </p>
*
* <pre>
* db = "bolt://localhost:7687"
* </pre>
*
* <pre>
* {
* use(new Neo4j());
*
* get("/", req {@literal ->} {
* // work with db
* DB = req.require(BoltDBAccess.class);
* });
* }
* </pre>
*
* Default DB connection info property is <code>db</code> but of course you can use any other name:
*
* <p>
* application.conf:
* </p>
*
* <pre>
* mydb = "bolt://localhost:7687"
* </pre>
*
* <pre>
* {
* use(new Neo4j("mydb"));
*
* get("/", req {@literal ->} {
* DB mydb = req.require(DB.class);
* // work with mydb
* });
* }
* </pre>
*
* <h1>options</h1>
* <p>
* Options can be set via <code>.conf</code> file:
* </p>
*
* <pre>
* neo4j.server_root_uri = "bolt://localhost:7687"
* </pre>
*
* <p>
* or programmatically:
* </p>
*
* <pre>
* {
* use(new Neo4j()
* .properties((properties, config) {@literal ->} {
* properties.put(DBProperties.SERVER_ROOT_URI, config.get("server_root_uri"))
* })
* );
* }
* </pre>
*
* <p>
* Default connection URI is defined by the <code>server_root_uri</code> property. Neo4j URI looks like:
* </p>
*
* <pre>
* bolt://host1[:port1]
* </pre>
*
* <p>
* Credentials have to be passed separately in <code>username</code> & <code>password</code> params.
* </p>
*
* <h1>two or more connections</h1>
*
* <pre>
* db1 = "bolt://localhost:7687"
* db2 = "bolt://localhost:7688"
* </pre>
*
* <pre>
* {
* use(new Neo4j("db1"));
* use(new Neo4j("db2"));
*
* get("/", req {@literal ->} {
* BoltDBAccess client1 = req.require("mydb1", BoltDBAccess.class);
* // work with mydb1
* BoltDBAccess client2 = req.require("mydb2", BoltDBAccess.class);
* // work with mydb1
* });
* }
* </pre>
*
* @author sbcd90
* @since 1.1.1
*/
public class Neo4j implements Jooby.Module {

private final String db;

private BiConsumer<Properties, Config> properties;

/**
* Creates a new {@link Neo4j} module.
*
* @param db Name of the property with the connection info.
*/
public Neo4j(final String db) {
this.db = requireNonNull(db, "A neo4j bolt configuration is required");
}

/**
* Creates a new {@link Neo4j} using the default property: <code>db</code>.
*/
public Neo4j() {
this("db");
}

@Override
public void configure(final Env env, final Config config, final Binder binder) {
Properties properties = options(neo4j(config));

if (nonNull(this.properties)) {
this.properties.accept(properties, config);
}

String dbUser = nonNull(properties.getProperty("username")) ? properties.getProperty("username"): "";
String dbPassword = nonNull(properties.getProperty("password")) ? properties.getProperty("password"): "";

BoltDBAccess remoteClient;
if (dbUser.isEmpty() && dbPassword.isEmpty()) {
remoteClient = (BoltDBAccess) DBAccessFactory.createDBAccess(DBType.REMOTE, properties);
} else {
remoteClient = (BoltDBAccess) DBAccessFactory.createDBAccess(DBType.REMOTE, properties, dbUser, dbPassword);
}
checkArgument(remoteClient.getSession() != null,
"Cannot connect to Database at: " + properties.get(DBProperties.SERVER_ROOT_URI));
String database = properties.getProperty(DBProperties.SERVER_ROOT_URI);

ServiceKey serviceKey = env.serviceKey();
serviceKey.generate(BoltDBAccess.class, database, k -> binder.bind(k).toInstance(remoteClient));

env.onStop(remoteClient::close);
}

/**
* Set a properties callback.
*
* <pre>
* {
* use(new Neo4j()
* .properties((properties, config) {@literal ->} {
* properties.put(DBProperties.ARRAY_BLOCK_SIZE, "120);
* })
* );
* }
* </pre>
*
* @param properties Configure callback.
* @return This module
*/
public Neo4j properties(final BiConsumer<Properties, Config> properties) {
this.properties = requireNonNull(properties, "properties callback is required");
return this;
}

@Override
public Config config() {
return ConfigFactory.parseResources(Neo4j.class, "neo4j.conf");
}

private Properties options(final Config config) {
Properties properties = new Properties();
properties.putAll(config.entrySet()
.stream()
.map(entry -> new SimpleEntry<>(entry.getKey(), entry.getValue().unwrapped()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));

return properties;
}

private Config neo4j(final Config config) {
Config $neo4j = config.getConfig("neo4j");

if (config.hasPath("neo4j." + db)) {
$neo4j = config.getConfig("neo4j." + db).withFallback($neo4j);
}
return $neo4j;
}
}
Loading

0 comments on commit 91c0231

Please sign in to comment.