attributes = session.attributes();
-
- try(Transaction tx = dbService.beginTx()) {
- Optional.ofNullable(dbService.findNode(Label.label(sessionLabel), "_id", id))
- .map(node -> {
- node.setProperty("_accessedAt", session.accessedAt());
- node.setProperty("_createdAt", session.createdAt());
- node.setProperty("_savedAt", session.savedAt());
-
- attributes.forEach((k, v) -> node.setProperty(encode(k), v));
-
- if (!node.hasProperty("_expire")) {
- node.setProperty("_expire", System.currentTimeMillis() + timeout * 1000);
- }
-
- return node;
- }).orElseGet(() -> {
- Node node = dbService.createNode(Label.label(sessionLabel));
-
- node.setProperty("_accessedAt", session.accessedAt());
- node.setProperty("_createdAt", session.createdAt());
- node.setProperty("_savedAt", session.savedAt());
-
- attributes.forEach((k, v) -> node.setProperty(encode(k), v));
- node.setProperty("_expire", System.currentTimeMillis() + timeout * 1000);
-
- return node;
- });
- tx.success();
- }
- }
-
- @Override
- public void create(Session session) {
- save(session);
- }
-
- @Override
- public void delete(String id) {
- try(Transaction tx = dbService.beginTx()) {
- dbService.findNode(Label.label(sessionLabel), "_id", id).delete();
- tx.success();
- }
- }
-
- private static long seconds(final String value) {
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException ex) {
- Config config = ConfigFactory.empty()
- .withValue("timeout", ConfigValueFactory.fromAnyRef(value));
- return config.getDuration("timeout", TimeUnit.SECONDS);
- } catch (NullPointerException ex) {
- return 1800L;
- }
- }
-
- private String encode(final String key) {
- String value = key;
- if (value.charAt(0) == DOLLAR) {
- value = UDOLLAR + value.substring(1);
- }
- return value.replace(DOT, UDOT);
- }
-
- private String decode(final String key) {
- String value = key;
- if (value.charAt(0) == UDOLLAR) {
- value = DOLLAR + value.substring(1);
- }
- return value.replace(UDOT, DOT);
- }
-}
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4j.java b/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4j.java
index 2ef72ee51e..e0266164a4 100644
--- a/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4j.java
+++ b/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4j.java
@@ -1,239 +1,656 @@
/**
- * 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.
+ * Apache License
+ * Version 2.0, January 2004
+ * http://www.apache.org/licenses/
+ *
+ * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ *
+ * 1. Definitions.
+ *
+ * "License" shall mean the terms and conditions for use, reproduction,
+ * and distribution as defined by Sections 1 through 9 of this document.
+ *
+ * "Licensor" shall mean the copyright owner or entity authorized by
+ * the copyright owner that is granting the License.
+ *
+ * "Legal Entity" shall mean the union of the acting entity and all
+ * other entities that control, are controlled by, or are under common
+ * control with that entity. For the purposes of this definition,
+ * "control" means (i) the power, direct or indirect, to cause the
+ * direction or management of such entity, whether by contract or
+ * otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ * outstanding shares, or (iii) beneficial ownership of such entity.
+ *
+ * "You" (or "Your") shall mean an individual or Legal Entity
+ * exercising permissions granted by this License.
+ *
+ * "Source" form shall mean the preferred form for making modifications,
+ * including but not limited to software source code, documentation
+ * source, and configuration files.
+ *
+ * "Object" form shall mean any form resulting from mechanical
+ * transformation or translation of a Source form, including but
+ * not limited to compiled object code, generated documentation,
+ * and conversions to other media types.
+ *
+ * "Work" shall mean the work of authorship, whether in Source or
+ * Object form, made available under the License, as indicated by a
+ * copyright notice that is included in or attached to the work
+ * (an example is provided in the Appendix below).
+ *
+ * "Derivative Works" shall mean any work, whether in Source or Object
+ * form, that is based on (or derived from) the Work and for which the
+ * editorial revisions, annotations, elaborations, or other modifications
+ * represent, as a whole, an original work of authorship. For the purposes
+ * of this License, Derivative Works shall not include works that remain
+ * separable from, or merely link (or bind by name) to the interfaces of,
+ * the Work and Derivative Works thereof.
+ *
+ * "Contribution" shall mean any work of authorship, including
+ * the original version of the Work and any modifications or additions
+ * to that Work or Derivative Works thereof, that is intentionally
+ * submitted to Licensor for inclusion in the Work by the copyright owner
+ * or by an individual or Legal Entity authorized to submit on behalf of
+ * the copyright owner. For the purposes of this definition, "submitted"
+ * means any form of electronic, verbal, or written communication sent
+ * to the Licensor or its representatives, including but not limited to
+ * communication on electronic mailing lists, source code control systems,
+ * and issue tracking systems that are managed by, or on behalf of, the
+ * Licensor for the purpose of discussing and improving the Work, but
+ * excluding communication that is conspicuously marked or otherwise
+ * designated in writing by the copyright owner as "Not a Contribution."
+ *
+ * "Contributor" shall mean Licensor and any individual or Legal Entity
+ * on behalf of whom a Contribution has been received by Licensor and
+ * subsequently incorporated within the Work.
+ *
+ * 2. Grant of Copyright License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * copyright license to reproduce, prepare Derivative Works of,
+ * publicly display, publicly perform, sublicense, and distribute the
+ * Work and such Derivative Works in Source or Object form.
+ *
+ * 3. Grant of Patent License. Subject to the terms and conditions of
+ * this License, each Contributor hereby grants to You a perpetual,
+ * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ * (except as stated in this section) patent license to make, have made,
+ * use, offer to sell, sell, import, and otherwise transfer the Work,
+ * where such license applies only to those patent claims licensable
+ * by such Contributor that are necessarily infringed by their
+ * Contribution(s) alone or by combination of their Contribution(s)
+ * with the Work to which such Contribution(s) was submitted. If You
+ * institute patent litigation against any entity (including a
+ * cross-claim or counterclaim in a lawsuit) alleging that the Work
+ * or a Contribution incorporated within the Work constitutes direct
+ * or contributory patent infringement, then any patent licenses
+ * granted to You under this License for that Work shall terminate
+ * as of the date such litigation is filed.
+ *
+ * 4. Redistribution. You may reproduce and distribute copies of the
+ * Work or Derivative Works thereof in any medium, with or without
+ * modifications, and in Source or Object form, provided that You
+ * meet the following conditions:
+ *
+ * (a) You must give any other recipients of the Work or
+ * Derivative Works a copy of this License; and
+ *
+ * (b) You must cause any modified files to carry prominent notices
+ * stating that You changed the files; and
+ *
+ * (c) You must retain, in the Source form of any Derivative Works
+ * that You distribute, all copyright, patent, trademark, and
+ * attribution notices from the Source form of the Work,
+ * excluding those notices that do not pertain to any part of
+ * the Derivative Works; and
+ *
+ * (d) If the Work includes a "NOTICE" text file as part of its
+ * distribution, then any Derivative Works that You distribute must
+ * include a readable copy of the attribution notices contained
+ * within such NOTICE file, excluding those notices that do not
+ * pertain to any part of the Derivative Works, in at least one
+ * of the following places: within a NOTICE text file distributed
+ * as part of the Derivative Works; within the Source form or
+ * documentation, if provided along with the Derivative Works; or,
+ * within a display generated by the Derivative Works, if and
+ * wherever such third-party notices normally appear. The contents
+ * of the NOTICE file are for informational purposes only and
+ * do not modify the License. You may add Your own attribution
+ * notices within Derivative Works that You distribute, alongside
+ * or as an addendum to the NOTICE text from the Work, provided
+ * that such additional attribution notices cannot be construed
+ * as modifying the License.
+ *
+ * You may add Your own copyright statement to Your modifications and
+ * may provide additional or different license terms and conditions
+ * for use, reproduction, or distribution of Your modifications, or
+ * for any such Derivative Works as a whole, provided Your use,
+ * reproduction, and distribution of the Work otherwise complies with
+ * the conditions stated in this License.
+ *
+ * 5. Submission of Contributions. Unless You explicitly state otherwise,
+ * any Contribution intentionally submitted for inclusion in the Work
+ * by You to the Licensor shall be under the terms and conditions of
+ * this License, without any additional terms or conditions.
+ * Notwithstanding the above, nothing herein shall supersede or modify
+ * the terms of any separate license agreement you may have executed
+ * with Licensor regarding such Contributions.
+ *
+ * 6. Trademarks. This License does not grant permission to use the trade
+ * names, trademarks, service marks, or product names of the Licensor,
+ * except as required for reasonable and customary use in describing the
+ * origin of the Work and reproducing the content of the NOTICE file.
+ *
+ * 7. Disclaimer of Warranty. Unless required by applicable law or
+ * agreed to in writing, Licensor provides the Work (and each
+ * Contributor provides its Contributions) on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied, including, without limitation, any warranties or conditions
+ * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ * PARTICULAR PURPOSE. You are solely responsible for determining the
+ * appropriateness of using or redistributing the Work and assume any
+ * risks associated with Your exercise of permissions under this License.
+ *
+ * 8. Limitation of Liability. In no event and under no legal theory,
+ * whether in tort (including negligence), contract, or otherwise,
+ * unless required by applicable law (such as deliberate and grossly
+ * negligent acts) or agreed to in writing, shall any Contributor be
+ * liable to You for damages, including any direct, indirect, special,
+ * incidental, or consequential damages of any character arising as a
+ * result of this License or out of the use or inability to use the
+ * Work (including but not limited to damages for loss of goodwill,
+ * work stoppage, computer failure or malfunction, or any and all
+ * other commercial damages or losses), even if such Contributor
+ * has been advised of the possibility of such damages.
+ *
+ * 9. Accepting Warranty or Additional Liability. While redistributing
+ * the Work or Derivative Works thereof, You may choose to offer,
+ * and charge a fee for, acceptance of support, warranty, indemnity,
+ * or other liability obligations and/or rights consistent with this
+ * License. However, in accepting such obligations, You may act only
+ * on Your own behalf and on Your sole responsibility, not on behalf
+ * of any other Contributor, and only if You agree to indemnify,
+ * defend, and hold each Contributor harmless for any liability
+ * incurred by, or claims asserted against, such Contributor by reason
+ * of your accepting any such warranty or additional liability.
+ *
+ * END OF TERMS AND CONDITIONS
+ *
+ * APPENDIX: How to apply the Apache License to your work.
+ *
+ * To apply the Apache License to your work, attach the following
+ * boilerplate notice, with the fields enclosed by brackets "{}"
+ * replaced with your own identifying information. (Don't include
+ * the brackets!) The text should be enclosed in the appropriate
+ * comment syntax for the file format. We also recommend that a
+ * file or class name and description of purpose be included on the
+ * same "printed page" as the copyright notice for easier
+ * identification within third-party archives.
+ *
+ * Copyright 2014 Edgar Espina
+ *
+ * Licensed 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 static iot.jcypher.database.DBProperties.DATABASE_DIR;
+import static iot.jcypher.database.DBProperties.SERVER_ROOT_URI;
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jooby.Env;
+import org.jooby.Env.ServiceKey;
+import org.jooby.Jooby.Module;
+import org.neo4j.driver.v1.AuthTokens;
+import org.neo4j.driver.v1.Driver;
+import org.neo4j.driver.v1.GraphDatabase;
+import org.neo4j.driver.v1.Session;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
+import org.neo4j.graphdb.factory.GraphDatabaseFactory;
+import org.neo4j.logging.slf4j.Slf4jLogProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
import com.google.inject.Binder;
import com.typesafe.config.Config;
+import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigFactory;
-import iot.jcypher.database.DBAccessFactory;
+import com.typesafe.config.ConfigValue;
+import com.typesafe.config.ConfigValueFactory;
+import com.typesafe.config.ConfigValueType;
+
import iot.jcypher.database.DBProperties;
-import iot.jcypher.database.DBType;
+import iot.jcypher.database.IDBAccess;
+import iot.jcypher.database.embedded.AbstractEmbeddedDBAccess;
+import iot.jcypher.database.embedded.EmbeddedDBAccess;
import iot.jcypher.database.remote.BoltDBAccess;
-import org.jooby.Env;
-import org.jooby.Jooby;
-
-import java.util.AbstractMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.function.BiConsumer;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.nonNull;
-import static java.util.Objects.requireNonNull;
/**
- * Exposes {@link BoltDBAccess}.
- *
- * usage
+ * neo4j
+ *
+ * Neo4j is a highly scalable native graph database that leverages
+ * data relationships as first-class entities, helping enterprises build intelligent applications to
+ * meet today’s evolving data challenges.
+ *
*
*
- * application.conf:
+ * This module give you access to neo4j and
+ * jcypher APIs.
*
*
- *
- * db = "bolt://localhost:7687"
- *
+ * exports
+ *
+ * - GraphDatabaseService for embedded neo4j instances.
+ * - Driver and Session objects for remote instances
+ * - IDBAccess object
+ *
*
- *
+ * usage
+ *
+ * {@code
* {
* use(new Neo4j());
*
- * get("/", req {@literal ->} {
- * // work with db
- * DB = req.require(BoltDBAccess.class);
+ * get("/driver", () -> {
+ * // work with driver
+ * Driver driver = require(Driver.class);
* });
- * }
- *
*
- * Default DB connection info property is db
but of course you can use any other name:
+ * get("/session", () -> {
+ * // work with session
+ * Session session = require(Session.class);
+ * });
+ *
+ * get("/dbaccess", () -> {
+ * // work with driver
+ * BoltDBAccess dbaccess = require(BoltDBAccess.class);
+ * });
+ * }
+ * }
*
*
- * application.conf:
+ * application.conf
*
- *
*
- * mydb = "bolt://localhost:7687"
+ * db.url = "bolt://localhost:7687"
+ * db.user = myuser
+ * db.password = mypassword
*
*
- *
- * {
- * use(new Neo4j("mydb"));
+ * embedded
+ *
+ * In addition to remote access using bolt
protocol, this module provide
+ * access to embedded
neo4j instances:
+ *
*
- * get("/", req {@literal ->} {
- * DB mydb = req.require(DB.class);
- * // work with mydb
- * });
+ *
+ * In memory mode:
+ *
+ * {@code
+ * {
+ * use(new Neo4j("mem"));
* }
- *
+ * }
*
- * options
*
- * Options can be set via .conf
file:
+ * File system mode:
*
+ * {@code
+ * {
+ * use(new Neo4j("fs"));
+ * }
+ * }
*
- *
- * neo4j.server_root_uri = "bolt://localhost:7687"
- *
+ *
+ * Optionally you can specify the desired path:
+ *
+ * {@code
+ * {
+ * use(new Neo4j(Paths.get("path", "mydb")));
+ * }
+ * }
*
*
- * or programmatically:
+ * The embedded mode allow you to access {@link GraphDatabaseService} instances:
*
*
- *
+ * {@code
* {
- * use(new Neo4j()
- * .properties((properties, config) {@literal ->} {
- * properties.put(DBProperties.SERVER_ROOT_URI, config.get("server_root_uri"))
- * })
- * );
+ * use(new Neo4j("mem"));
+ *
+ * get("/", () -> {
+ * GraphDatabaseService db = require(GraphDatabaseService.class);
+ * });
* }
- *
+ * }
*
*
- * Default connection URI is defined by the server_root_uri
property. Neo4j URI looks like:
+ * As well as {@link EmbeddedDBAccess}:
+ *
+ * {@code
+ * {
+ * use(new Neo4j("mem"));
+ *
+ * get("/", () -> {
+ * EmbeddedDBAccess db = require(EmbeddedDBAccess.class);
+ * });
+ * }
+ * }
+ *
+ * runtime modules
+ *
+ * This option is available for embedded
Neo4j instances and we allow to configure one
+ * or more runtime modules via .conf
file:
*
*
*
- * bolt://host1[:port1]
+ * com.graphaware.runtime.enabled = true
+ *
+ * com.graphaware.module = [{
+ * class: com.graphaware.neo4j.expire.ExpirationModuleBootstrapper
+ * nodeExpirationProperty: _expire
+ * }, {
+ * class: com.graphaware.neo4j.expire.AnotherModule
+ * modProp: modValue
+ * }]
*
*
*
- * Credentials have to be passed separately in username
& password
params.
+ * You first need to enabled
the graph runtime framework by setting the
+ * com.graphaware.runtime.enabled
property.
*
*
- * two or more connections
+ *
+ * Then you need to add one or more modules under the com.graphaware.module
+ * property path.
+ *
*
- *
- * db1 = "bolt://localhost:7687"
- * db2 = "bolt://localhost:7688"
- *
+ * two or more connections
+ *
+ * Two or more connection is available by setting and installing multiples {@link Neo4j} modules:
+ *
*
- *
+ * {@code
* {
* 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
+ * get("/", () -> {
+ * Driver db1 = require("db1", Driver.class);
+ * BoltDBAccess bolt1 = require("db1", BoltDBAccess.class);
+ *
+ * Driver db2 = require("db2", Driver.class);
+ * BoltDBAccess bolt2 = require("db2", BoltDBAccess.class);
* });
* }
+ * }
+ *
+ *
+ * application.conf:
+ *
+ *
+ *
+ * db1.url = "bolt://localhost:7687"
+ * db1.user = db1user
+ * db1.password = db1pass
+ *
+ * db2.url = "bolt://localhost:7687"
+ * db2.user = db2user
+ * db2.password = db2pass
*
*
+ * options
+ *
+ * Neo4j options are available via .conf
file:
+ *
+ *
+ *
+ * neo4j.dbms.read_only = true
+ * neo4j.unsupported.dbms.block_size.array_properties = 120
+ *
+ *
+ * @author edgar
* @author sbcd90
- * @since 1.2.0
*/
-public class Neo4j implements Jooby.Module {
+public class Neo4j implements Module {
+
+ static {
+ if (!SLF4JBridgeHandler.isInstalled()) {
+ SLF4JBridgeHandler.removeHandlersForRootLogger();
+ SLF4JBridgeHandler.install();
+ }
+ }
- private final String db;
+ /** The logging system. */
+ private final Logger log = LoggerFactory.getLogger(getClass());
- private BiConsumer properties;
+ private String db;
/**
* Creates a new {@link Neo4j} module.
*
- * @param db Name of the property with the connection info.
+ * @param db Database type: mem
, fs
,
+ * path
for embedded database or property
pointing the
+ * a database server or one of the previously described values.
*/
public Neo4j(final String db) {
- this.db = requireNonNull(db, "A neo4j bolt configuration is required");
+ this.db = requireNonNull(db, "Database required.");
+ }
+
+ /**
+ * Creates a new embedded {@link Neo4j} module.
+ *
+ * @param db Path to store the database.
+ */
+ public Neo4j(final Path db) {
+ this(db.toAbsolutePath().toString());
}
/**
- * Creates a new {@link Neo4j} using the default property: db
.
+ * Creates a new {@link Neo4j} module a db
property must be defined in your
+ * .conf
file. Property value must be one of: mem
, fs
,
+ * file system path
or bolt url
.
+ *
*/
public Neo4j() {
this("db");
}
+ @SuppressWarnings({"unchecked", "rawtypes" })
@Override
- public void configure(final Env env, final Config config, final Binder binder) {
- Properties properties = options(neo4j(config));
+ public void configure(final Env env, final Config conf, final Binder binder) throws Throwable {
+ String db = database(conf, this.db);
+ Properties props = props(neo4j(conf, this.db));
- if (nonNull(this.properties)) {
- this.properties.accept(properties, config);
- }
+ ServiceKey keys = env.serviceKey();
+ IDBAccess dbaccess = dbaccess(conf, this.db, db, props, keys, binder);
+
+ Arrays.asList(props.getProperty(SERVER_ROOT_URI), props.getProperty(DATABASE_DIR))
+ .stream()
+ .filter(Objects::nonNull)
+ .findFirst()
+ .ifPresent(it -> log.info("Starting neo4j: {}", it));
+
+ Class dbaccessType = dbaccess.getClass();
+ keys.generate(IDBAccess.class, this.db, k -> binder.bind(k).toInstance(dbaccess));
+ keys.generate(dbaccessType, this.db, k -> binder.bind(k).toInstance(dbaccess));
+
+ env.onStop(dbaccess::close);
+ }
+
+ @Override
+ public Config config() {
+ return ConfigFactory.empty(getClass().getName().toLowerCase() + ".conf")
+ .withValue("neo4j.session.label", ConfigValueFactory.fromAnyRef("session"));
+ }
- String dbUser = nonNull(properties.getProperty("username")) ? properties.getProperty("username"): "";
- String dbPassword = nonNull(properties.getProperty("password")) ? properties.getProperty("password"): "";
+ private Config neo4j(final Config conf, final String db) {
+ Config result = conf.hasPath("com.graphaware")
+ ? ConfigFactory.empty().withValue("com.graphaware", conf.getConfig("com.graphaware").root())
+ : ConfigFactory.empty();
+ String[] paths = {"neo4j", db, "neo4j." + db };
+ for (String path : paths) {
+ try {
+ if (conf.hasPath(path)) {
+ Config it = conf.getConfig(path);
+ result = it.withFallback(result);
+ }
+ } catch (ConfigException x) {
+ // Skip/ignore bad path
+ }
+ }
+ return result;
+ }
- BoltDBAccess remoteClient;
- if (dbUser.isEmpty() && dbPassword.isEmpty()) {
- remoteClient = (BoltDBAccess) DBAccessFactory.createDBAccess(DBType.REMOTE, properties);
- } else {
- remoteClient = (BoltDBAccess) DBAccessFactory.createDBAccess(DBType.REMOTE, properties, dbUser, dbPassword);
+ @SuppressWarnings("deprecation")
+ private IDBAccess dbaccess(final Config conf, final String dbkey, final String db,
+ final Properties props, final Env.ServiceKey keys, final Binder binder) throws Exception {
+ // remote
+ if (db.startsWith("bolt")) {
+ String username = conf.getString(dbkey + ".user");
+ String password = conf.getString(dbkey + ".password");
+ Driver driver = GraphDatabase.driver(db, AuthTokens.basic(username, password));
+ Session session = driver.session();
+ props.setProperty(DBProperties.SERVER_ROOT_URI, db);
+ keys.generate(Driver.class, dbkey, k -> binder.bind(k).toInstance(driver));
+ keys.generate(Session.class, dbkey, k -> binder.bind(k).toInstance(session));
+ BoltDBAccess dbaccess = new BoltDBAccess();
+ dbaccess.initialize(props);
+ driverhack(dbaccess, driver);
+ return dbaccess;
+ }
+ boolean mem = db.equals("mem");
+ Path path = (db.equals("fs") || mem
+ ? Paths.get(conf.getString("application.tmpdir")).resolve("neo4j" + db)
+ : Paths.get(db)).toAbsolutePath();
+ props.setProperty(DBProperties.DATABASE_DIR, path.toString());
+ if (mem) {
+ // clean up existing database
+ rm(path);
}
- checkArgument(remoteClient.getSession() != null,
- "Cannot connect to Database at: " + properties.get(DBProperties.SERVER_ROOT_URI));
- String database = properties.getProperty(DBProperties.SERVER_ROOT_URI);
+ GraphDatabaseBuilder builder = new GraphDatabaseFactory()
+ .setUserLogProvider(new Slf4jLogProvider())
+ .newEmbeddedDatabaseBuilder(path.toFile());
+ props.forEach((k, v) -> builder.setConfig(k.toString(), v.toString()));
+ GraphDatabaseService graphDatabaseService = builder.newGraphDatabase();
+ keys.generate(GraphDatabaseService.class, dbkey,
+ k -> binder.bind(k).toInstance(graphDatabaseService));
- Env.ServiceKey serviceKey = env.serviceKey();
- serviceKey.generate(BoltDBAccess.class, database, k -> binder.bind(k).toInstance(remoteClient));
+ EmbeddedDBAccess dbaccess = new EmbeddedDBAccess();
+ dbaccess.initialize(props);
+ dbServicehack(dbaccess, graphDatabaseService);
- env.onStop(remoteClient::close);
+ return dbaccess;
}
- /**
- * Set a properties callback.
- *
- *
- * {
- * use(new Neo4j()
- * .properties((properties, config) {@literal ->} {
- * properties.put(DBProperties.ARRAY_BLOCK_SIZE, "120);
- * })
- * );
- * }
- *
- *
- * @param properties Configure callback.
- * @return This module
- */
- public Neo4j properties(final BiConsumer properties) {
- this.properties = requireNonNull(properties, "properties callback is required");
- return this;
+ private String database(final Config conf, final String db) {
+ String[] paths = {db + ".url", db };
+ for (String path : paths) {
+ if (conf.hasPath(path)) {
+ return conf.getString(path);
+ }
+ }
+ if (db.equals("db")) {
+ throw new ConfigException.Missing(db);
+ }
+ // path
+ return db;
}
- @Override
- public Config config() {
- return ConfigFactory.parseResources(Neo4j.class, "neo4j.conf");
+ private Properties props(final Config conf) {
+ Properties props = new Properties();
+ conf.entrySet().stream()
+ .filter(it -> !it.getKey().startsWith("com.graphaware.module"))
+ .forEach(prop -> {
+ String key = prop.getKey();
+ Object value = prop.getValue().unwrapped();
+ props.put(key, value);
+ });
+ // write module:
+ if (conf.hasPath("com.graphaware.module")) {
+ ConfigValue raw = conf.getValue("com.graphaware.module");
+ List modules = new ArrayList<>();
+ if (raw.valueType() == ConfigValueType.LIST) {
+ modules.addAll(conf.getConfigList("com.graphaware.module"));
+ } else {
+ modules.add(conf.getConfig("com.graphaware.module"));
+ }
+ AtomicInteger nextOrder = new AtomicInteger(0);
+ modules.forEach(module -> {
+ String type = module.getString("class");
+ int order = nextOrder.incrementAndGet();
+ String key = "com.graphaware.module.m" + order;
+ props.put(key + "." + order, type);
+ module.withoutPath("class").root()
+ .forEach((k, v) -> props.put(key + "." + k, v.unwrapped().toString()));
+ });
+ }
+ log.debug("neo4j properties: {}", props);
+ return props;
}
- private Properties options(final Config config) {
- Properties properties = new Properties();
- properties.putAll(config.entrySet()
- .stream()
- .map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().unwrapped()))
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
+ static void driverhack(final BoltDBAccess dbaccess, final Driver value) throws Exception {
+ fieldhack(BoltDBAccess.class, dbaccess, "driver", value);
+ }
+
+ static void dbServicehack(final EmbeddedDBAccess dbaccess, final GraphDatabaseService value)
+ throws Exception {
+ fieldhack(AbstractEmbeddedDBAccess.class, dbaccess, "graphDb", value);
+ }
- return properties;
+ @SuppressWarnings("rawtypes")
+ static void fieldhack(final Class owner, final Object instance, final String name,
+ final Object value) throws Exception {
+ Field field = owner.getDeclaredField(name);
+ field.setAccessible(true);
+ field.set(instance, value);
}
- private Config neo4j(final Config config) {
- Config $neo4j = config.getConfig("neo4j");
+ static void rm(final Path path) throws IOException {
+ if (Files.exists(path)) {
+ Files.walkFileTree(path, new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
+ throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(final Path dir, final IOException exc)
+ throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
- if (config.hasPath("neo4j." + db)) {
- $neo4j = config.getConfig("neo4j." + db).withFallback($neo4j);
+ });
}
- return $neo4j;
}
-}
\ No newline at end of file
+}
diff --git a/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4jSessionStore.java b/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4jSessionStore.java
index 7ffe36198f..fc9db71b52 100644
--- a/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4jSessionStore.java
+++ b/modules/jooby-neo4j/src/main/java/org/jooby/neo4j/Neo4jSessionStore.java
@@ -19,31 +19,41 @@
package org.jooby.neo4j;
-import com.graphaware.neo4j.expire.ExpirationModule;
-import com.graphaware.neo4j.expire.config.ExpirationConfiguration;
-import com.graphaware.runtime.GraphAwareRuntime;
-import com.graphaware.runtime.GraphAwareRuntimeFactory;
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import com.typesafe.config.ConfigValueFactory;
-import org.apache.commons.lang3.tuple.Pair;
-import org.jooby.Session;
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.Label;
-import org.neo4j.graphdb.Node;
-import org.neo4j.graphdb.Transaction;
-import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
+import static java.util.Objects.requireNonNull;
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.io.File;
-import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.function.LongSupplier;
+import java.util.stream.Collectors;
-import static java.util.Objects.requireNonNull;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jooby.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableSet;
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+import iot.jcypher.database.IDBAccess;
+import iot.jcypher.graph.GrNode;
+import iot.jcypher.graph.GrProperty;
+import iot.jcypher.query.JcQuery;
+import iot.jcypher.query.JcQueryResult;
+import iot.jcypher.query.api.IClause;
+import iot.jcypher.query.api.pattern.Node;
+import iot.jcypher.query.factories.clause.CREATE;
+import iot.jcypher.query.factories.clause.DO;
+import iot.jcypher.query.factories.clause.MATCH;
+import iot.jcypher.query.factories.clause.RETURN;
+import iot.jcypher.query.values.JcNode;
/**
* A {@link Session.Store} powered by
@@ -85,16 +95,39 @@
*
*
*
- * It uses GraphAware's Expire library to automatically remove
- * expired sessions.
+ * It uses GraphAware's Expire library to
+ * automatically remove expired sessions.
+ *
+ *
+ *
+ * For embedded databases you need to configure the expire module, like:
+ *
+ *
+ *
+ * com.graphaware.runtime.enabled = true
+ *
+ * com.graphaware.module = [{
+ * class: com.graphaware.neo4j.expire.ExpirationModuleBootstrapper
+ * nodeExpirationProperty: _expire
+ * }]
+ *
+ *
+ *
+ * The {@link Neo4jSessionStore} uses the _expire
to evict sessions.
*
*
+ *
+ * If you connect to a remote server make sure the expire module was installed. More information at
+ * .
+ *
+ *
+ *
* If no timeout is required, use -1
.
+ *
*
* session label
*
- * It's possible to provide the session label using the neo4j.session.label
- * properties.
+ * It's possible to provide the session label using the neo4j.session.label
properties.
*
*
* @author sbcd90
@@ -102,110 +135,130 @@
*/
public class Neo4jSessionStore implements Session.Store {
- private static final char DOT = '.';
-
- private static final char UDOT = '\uFF0E';
-
- private static final char DOLLAR = '$';
-
- private static final char UDOLLAR = '\uFF04';
-
- protected final String sessionLabel;
+ private final Set SPECIAL = ImmutableSet.of("_accessedAt", "_createdAt", "_savedAt",
+ "_expire", "_id");
- protected final long timeout;
+ /** The logging system. */
+ private final Logger log = LoggerFactory.getLogger(getClass());
- private static GraphDatabaseService dbService;
- private static GraphAwareRuntime graphRuntime;
+ private final String label;
- protected final GraphDatabaseService db;
- protected final GraphAwareRuntime graphAwareRuntime;
+ private final LongSupplier expire;
+ private final IDBAccess db;
- public Neo4jSessionStore(Pair graph, final String sessionLabel,
- final long timeoutInSeconds) {
- this.db = requireNonNull(graph.getLeft(), "GraphDatabaseService instance is required");
- this.graphAwareRuntime = requireNonNull(graph.getRight(), "GraphAwareRuntime instance is required");
- this.sessionLabel = requireNonNull(sessionLabel, "Label to store sessions is required");
- this.timeout = timeoutInSeconds;
+ public Neo4jSessionStore(final IDBAccess dbaccess, final String sessionLabel,
+ final long timeoutInSeconds) {
+ this.db = dbaccess;
+ this.label = requireNonNull(sessionLabel, "Label to store sessions is required");
+ long expire = TimeUnit.SECONDS.toMillis(timeoutInSeconds);
+ this.expire = () -> System.currentTimeMillis() + expire;
}
@Inject
- public Neo4jSessionStore(@Named("databaseDir") String databaseDir,
- final @Named("neo4j.session.label") String sessionLabel,
- final @Named("session.timeout") String timeout) {
- this(getOrCreateGraph(databaseDir), sessionLabel, seconds(timeout));
+ public Neo4jSessionStore(final IDBAccess dbaccess,
+ final @Named("neo4j.session.label") String sessionLabel,
+ final @Named("session.timeout") String timeout) {
+ this(dbaccess, sessionLabel, seconds(timeout));
}
@Override
public Session get(final Session.Builder builder) {
- try(Transaction tx = db.beginTx()) {
- return Optional.ofNullable(db.findNode(Label.label(sessionLabel), "_id", builder.sessionId()))
- .map(node -> {
- Map session = new LinkedHashMap<>(node.getAllProperties());
-
- Long accessedAt = (Long) session.remove("_accessedAt");
- Long createdAt = (Long) session.remove("_createdAt");
- Long savedAt = (Long) session.remove("_savedAt");
- session.remove("_id");
- session.remove("_expire");
-
- builder
- .accessedAt(accessedAt)
- .createdAt(createdAt)
- .savedAt(savedAt);
- session.forEach((k, v) -> builder.set(decode(k), v.toString()));
- tx.success();
- return builder.build();
- }).orElse(null);
+ String sid = builder.sessionId();
+ JcNode node = new JcNode("n");
+ JcQuery query = new JcQuery();
+ query.setClauses(new IClause[]{
+ MATCH.node(node).label(label).property("_id").value(sid),
+ // touch session
+ DO.SET(node.property("_expire")).to(expire.getAsLong()),
+ RETURN.value(node)
+ });
+
+ List result = db.execute(query).resultOf(node);
+ log.debug("touch {} session {} ", sid, result);
+ if (result.size() == 1) {
+ GrNode found = result.get(0);
+ builder
+ .accessedAt(((Number) found.getProperty("_accessedAt").getValue()).longValue())
+ .createdAt(((Number) found.getProperty("_createdAt").getValue()).longValue())
+ .savedAt(((Number) found.getProperty("_savedAt").getValue()).longValue());
+
+ found.getProperties()
+ .stream()
+ .filter(it -> !SPECIAL.contains(it.getName()))
+ .forEach(p -> builder.set(p.getName(), p.getValue().toString()));
+
+ return builder.build();
}
+
+ return null;
}
@Override
public void save(final Session session) {
- String id = session.id();
- Map attributes = session.attributes();
-
- try(Transaction tx = db.beginTx()) {
- Optional.ofNullable(db.findNode(Label.label(sessionLabel), "_id", id))
- .map(node -> {
- node.setProperty("_accessedAt", session.accessedAt());
- node.setProperty("_createdAt", session.createdAt());
- node.setProperty("_savedAt", session.savedAt());
-
- attributes.forEach((k ,v) -> node.setProperty(encode(k), v));
-
- if (!node.hasProperty("_expire")) {
- node.setProperty("_expire", System.currentTimeMillis() + timeout * 1000);
- }
-
- return node;
- }).orElseGet(() -> {
- Node node = db.createNode(Label.label(sessionLabel));
-
- node.setProperty("_accessedAt", session.accessedAt());
- node.setProperty("_createdAt", session.createdAt());
- node.setProperty("_savedAt", session.savedAt());
-
- attributes.forEach((k, v) -> node.setProperty(encode(k), v));
- node.setProperty("_expire", System.currentTimeMillis() + timeout * 1000);
-
- return node;
- });
- tx.success();
+ String sid = session.id();
+ Map attributes = new HashMap<>(session.attributes());
+
+ JcNode node = new JcNode("n");
+ JcQuery query = new JcQuery();
+ List clauses = new ArrayList<>();
+ clauses.add(MATCH.node(node).label(label).property("_id").value(sid));
+ attributes.put("_accessedAt", session.accessedAt());
+ attributes.put("_createdAt", session.createdAt());
+ attributes.put("_savedAt", session.savedAt());
+ attributes.put("_expire", expire.getAsLong());
+ attributes.forEach((k, v) -> {
+ clauses.add(DO.SET(node.property(k)).to(v));
+ });
+ clauses.add(RETURN.value(node));
+
+ query.setClauses(clauses.toArray(new IClause[clauses.size()]));
+ List nodes = db.execute(query).resultOf(node);
+ if (nodes.size() == 1) {
+ GrNode found = nodes.get(0);
+ Set keys = found.getProperties().stream()
+ .map(GrProperty::getName)
+ .collect(Collectors.toSet());
+ keys.removeAll(attributes.keySet());
+ // unset properties
+ if (keys.size() > 0) {
+ log.debug("removing {} => {}", sid, keys);
+ JcQuery unsetQuery = new JcQuery();
+ List unsetClauses = new ArrayList<>();
+ unsetClauses.add(MATCH.node(node).label(label).property("_id").value(sid));
+ keys.forEach(key -> unsetClauses.add(DO.REMOVE(node.property(key))));
+ unsetQuery.setClauses(unsetClauses.toArray(new IClause[unsetClauses.size()]));
+ db.execute(unsetQuery);
+ }
+ log.debug("saved {} => {}", sid, nodes);
+ } else {
+ // create session:
+ query = new JcQuery();
+ Node create = CREATE.node(node).label(label);
+ create.property("_id").value(sid);
+ attributes.forEach((k, v) -> create.property(k).value(v));
+
+ query.setClauses(new IClause[]{create });
+ List result = db.execute(query).resultOf(node);
+ log.debug("created {} => {}", sid, result);
}
}
@Override
- public void create(Session session) {
+ public void create(final Session session) {
save(session);
}
@Override
- public void delete(String id) {
- try(Transaction tx = db.beginTx()) {
- db.findNode(Label.label(sessionLabel), "_id", id).delete();
- tx.success();
- }
+ public void delete(final String id) {
+ JcNode session = new JcNode("n");
+ JcQuery q = new JcQuery();
+ q.setClauses(new IClause[]{
+ MATCH.node(session).label(label).property("_id").value(id),
+ DO.DELETE(session)
+ });
+ JcQueryResult rsp = db.execute(q);
+ log.debug("destroyed {} => {}", id, rsp);
}
private static long seconds(final String value) {
@@ -213,43 +266,8 @@ private static long seconds(final String value) {
return Long.parseLong(value);
} catch (NumberFormatException ex) {
Config config = ConfigFactory.empty()
- .withValue("timeout", ConfigValueFactory.fromAnyRef(value));
+ .withValue("timeout", ConfigValueFactory.fromAnyRef(value));
return config.getDuration("timeout", TimeUnit.SECONDS);
- } catch (NullPointerException ex) {
- return 1800L;
- }
- }
-
- private String encode(final String key) {
- String value = key;
- if (value.charAt(0) == DOLLAR) {
- value = UDOLLAR + value.substring(1);
- }
- return value.replace(DOT, UDOT);
- }
-
- private String decode(final String key) {
- String value = key;
- if (value.charAt(0) == UDOLLAR) {
- value = DOLLAR + value.substring(1);
- }
- return value.replace(UDOT, DOT);
- }
-
- private static Pair getOrCreateGraph(String databaseDir) {
- if (dbService == null && graphRuntime == null) {
- GraphDatabaseBuilder builder = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(new File(databaseDir));
- dbService = builder.newGraphDatabase();
- graphRuntime = GraphAwareRuntimeFactory.createRuntime(dbService);
-
- ExpirationConfiguration configuration = ExpirationConfiguration.defaultConfiguration().withNodeExpirationProperty("_expire");
- graphRuntime.registerModule(new ExpirationModule("EXP", dbService, configuration));
-
- graphRuntime.start();
- graphRuntime.waitUntilStarted();
-
- return Pair.of(dbService, graphRuntime);
}
- return Pair.of(dbService, graphRuntime);
}
-}
\ No newline at end of file
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/embedded/neo4j/EmbeddedNeo4jApp.java b/modules/jooby-neo4j/src/test/java/apps/embedded/neo4j/EmbeddedNeo4jApp.java
deleted file mode 100644
index c166af760f..0000000000
--- a/modules/jooby-neo4j/src/test/java/apps/embedded/neo4j/EmbeddedNeo4jApp.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package apps.embedded.neo4j;
-
-import org.jooby.Jooby;
-import org.jooby.Session;
-import org.jooby.embedded.neo4j.EmbeddedNeo4j;
-import org.jooby.embedded.neo4j.EmbeddedNeo4jSessionStore;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class EmbeddedNeo4jApp extends Jooby {
-
- {
-
- conf("embedded/application.conf");
-
- use(new EmbeddedNeo4j());
-
- AtomicInteger inc = new AtomicInteger(0);
- session(EmbeddedNeo4jSessionStore.class);
-
- get("/", req -> {
- Session session = req.ifSession().orElseGet(() -> {
- Session newSession = req.session();
- int next = newSession.get("inc").intValue(inc.getAndIncrement());
- newSession.set("inc", next);
- return newSession;
- });
- return session.get("inc");
- });
- }
-
- public static void main(String[] args) {
- run(EmbeddedNeo4jApp::new, args);
- }
-}
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltApp.java
new file mode 100644
index 0000000000..cac86b666e
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltApp.java
@@ -0,0 +1,30 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+import iot.jcypher.database.remote.BoltDBAccess;
+
+public class Neo4jBoltApp extends Jooby {
+
+ {
+ use(ConfigFactory.empty()
+ .withValue("db.url", ConfigValueFactory.fromAnyRef("bolt://localhost:7687"))
+ .withValue("db.user", ConfigValueFactory.fromAnyRef("neo4j"))
+ .withValue("db.password", ConfigValueFactory.fromAnyRef("development")));
+
+ use(new Neo4j());
+
+ onStart(() -> {
+ System.out.println(require(BoltDBAccess.class).getSession());
+ });
+
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jBoltApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltSessionApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltSessionApp.java
new file mode 100644
index 0000000000..d40739c4a9
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jBoltSessionApp.java
@@ -0,0 +1,57 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.Session;
+import org.jooby.neo4j.Neo4j;
+import org.jooby.neo4j.Neo4jSessionStore;
+
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+import iot.jcypher.database.IDBAccess;
+
+public class Neo4jBoltSessionApp extends Jooby {
+
+ {
+ use(ConfigFactory.empty()
+ .withValue("db.url", ConfigValueFactory.fromAnyRef("bolt://localhost:7687"))
+ .withValue("db.user", ConfigValueFactory.fromAnyRef("neo4j"))
+ .withValue("db.password", ConfigValueFactory.fromAnyRef("development")));
+
+ use(new Neo4j());
+
+ session(Neo4jSessionStore.class);
+
+ get("/set", req -> {
+ String attr = req.param("attr").value("foo");
+ Session session = req.session();
+ session.set("attr", attr);
+ return attr;
+ });
+
+ get("/get", req -> {
+ Session session = req.session();
+ return session.get("attr").value();
+ });
+
+ get("/remove", req -> {
+ Session session = req.session();
+ return session.unset("attr").value();
+ });
+
+ get("/clear", req -> {
+ IDBAccess db = require(IDBAccess.class);
+ db.clearDatabase();
+ return "done";
+ });
+
+ get("/destroy", req -> {
+ req.session().destroy();
+ return "destroy";
+ });
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jBoltSessionApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp.java
new file mode 100644
index 0000000000..919ae6a866
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp.java
@@ -0,0 +1,28 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+import org.neo4j.graphdb.GraphDatabaseService;
+
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+public class Neo4jFsApp extends Jooby {
+
+ {
+ use(ConfigFactory.empty()
+ .withValue("com.graphaware.runtime.enabled", ConfigValueFactory.fromAnyRef(true))
+ .withValue("db", ConfigValueFactory.fromAnyRef("fs")));
+
+ use(new Neo4j("target/localdb"));
+
+ onStart(() -> {
+ System.out.println(require(GraphDatabaseService.class));
+ });
+
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jFsApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp2.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp2.java
new file mode 100644
index 0000000000..a7f75fc613
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jFsApp2.java
@@ -0,0 +1,21 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+import org.neo4j.graphdb.GraphDatabaseService;
+
+public class Neo4jFsApp2 extends Jooby {
+
+ {
+ use(new Neo4j("fs"));
+
+ onStart(() -> {
+ System.out.println(require(GraphDatabaseService.class));
+ });
+
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jFsApp2::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp.java
new file mode 100644
index 0000000000..6e12d46875
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp.java
@@ -0,0 +1,26 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+import org.neo4j.graphdb.GraphDatabaseService;
+
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+public class Neo4jInMemoryApp extends Jooby {
+
+ {
+ use(ConfigFactory.empty()
+ .withValue("db", ConfigValueFactory.fromAnyRef("mem")));
+ use(new Neo4j());
+
+ onStart(() -> {
+ System.out.println(require(GraphDatabaseService.class));
+ });
+
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jInMemoryApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp2.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp2.java
new file mode 100644
index 0000000000..f6ffd1aba4
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jInMemoryApp2.java
@@ -0,0 +1,21 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+import org.neo4j.graphdb.GraphDatabaseService;
+
+public class Neo4jInMemoryApp2 extends Jooby {
+
+ {
+ use(new Neo4j("mem"));
+
+ onStart(() -> {
+ System.out.println(require(GraphDatabaseService.class));
+ });
+
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jInMemoryApp2::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jSessionApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jSessionApp.java
new file mode 100644
index 0000000000..9f0c763b28
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jSessionApp.java
@@ -0,0 +1,61 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.Session;
+import org.jooby.neo4j.Neo4j;
+import org.jooby.neo4j.Neo4jSessionStore;
+
+import com.google.common.collect.ImmutableMap;
+import com.graphaware.neo4j.expire.ExpirationModuleBootstrapper;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
+
+import iot.jcypher.database.IDBAccess;
+
+public class Neo4jSessionApp extends Jooby {
+
+ {
+ use(ConfigFactory.empty()
+ .withValue("session.timeout", ConfigValueFactory.fromAnyRef(30))
+ .withValue("com.graphaware.runtime.enabled", ConfigValueFactory.fromAnyRef(true))
+ .withValue("com.graphaware.module", ConfigValueFactory.fromAnyRef(
+ (ImmutableMap.of("class", ExpirationModuleBootstrapper.class.getName(),
+ "nodeExpirationProperty", "_expire")))));
+
+ use(new Neo4j("mem"));
+
+ session(Neo4jSessionStore.class);
+
+ get("/set", req -> {
+ String attr = req.param("attr").value("foo");
+ Session session = req.session();
+ session.set("attr", attr);
+ return attr;
+ });
+
+ get("/get", req -> {
+ Session session = req.session();
+ return session.get("attr").value();
+ });
+
+ get("/unset", req -> {
+ Session session = req.session();
+ return session.unset("attr").value();
+ });
+
+ get("/clear", req -> {
+ IDBAccess db = require(IDBAccess.class);
+ db.clearDatabase();
+ return "done";
+ });
+
+ get("/destroy", req -> {
+ req.session().destroy();
+ return "destroy";
+ });
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jSessionApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jWrongApp.java b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jWrongApp.java
new file mode 100644
index 0000000000..0eafcb9c6a
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/apps/neo4j/Neo4jWrongApp.java
@@ -0,0 +1,15 @@
+package apps.neo4j;
+
+import org.jooby.Jooby;
+import org.jooby.neo4j.Neo4j;
+
+public class Neo4jWrongApp extends Jooby {
+
+ {
+ use(new Neo4j());
+ }
+
+ public static void main(final String[] args) {
+ run(Neo4jWrongApp::new, args);
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jSessionStoreTest.java b/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jSessionStoreTest.java
deleted file mode 100644
index ce8d2dd520..0000000000
--- a/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jSessionStoreTest.java
+++ /dev/null
@@ -1,242 +0,0 @@
-package org.jooby.embedded.neo4j;
-
-import com.google.common.collect.ImmutableMap;
-import com.graphaware.neo4j.expire.ExpirationModule;
-import com.graphaware.runtime.GraphAwareRuntime;
-import org.jooby.Session;
-import org.jooby.test.MockUnit;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.Label;
-import org.neo4j.graphdb.Node;
-import org.neo4j.graphdb.Transaction;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.function.BiConsumer;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
-import static org.junit.Assert.assertEquals;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({EmbeddedNeo4jSessionStore.class, LinkedHashMap.class, ExpirationModule.class})
-public class EmbeddedNeo4jSessionStoreTest {
- private static GraphDatabaseService dbService;
- private static GraphAwareRuntime graphAwareRuntime;
- private static Session.Builder sb;
-
- @SuppressWarnings("unchecked")
- MockUnit.Block boot = unit -> {
- dbService = unit.get(GraphDatabaseService.class);
- graphAwareRuntime = unit.get(GraphAwareRuntime.class);
- ExpirationModule expirationModule = unit.get(ExpirationModule.class);
- expect(graphAwareRuntime.getModule(isA(ExpirationModule.class.getClass()))).andReturn(expirationModule);
- graphAwareRuntime.start();
- expectLastCall();
- graphAwareRuntime.waitUntilStarted();
- expectLastCall();
- };
-
- long now = System.currentTimeMillis();
-
- Map attrs = ImmutableMap.of("k.v", "v", "$d", "d");
- Map properties;
-
- MockUnit.Block saveSession = unit -> {
-
- Session session = unit.get(Session.class);
- expect(session.id()).andReturn("1234");
- expect(session.accessedAt()).andReturn(now);
- expect(session.createdAt()).andReturn(now);
- expect(session.savedAt()).andReturn(now);
- expect(session.attributes()).andReturn(attrs);
-
- Node node = unit.mock(Node.class);
- node.setProperty(isA(String.class), isA(Object.class));
- expectLastCall().anyTimes();
- expect(node.hasProperty(isA(String.class))).andReturn(false);
- expect(dbService.findNode(isA(Label.class), isA(String.class), isA(Object.class))).andReturn(node);
- };
-
- MockUnit.Block updateSession = unit -> {
-
- Session session = unit.get(Session.class);
- expect(session.id()).andReturn("1234");
- expect(session.accessedAt()).andReturn(now);
- expect(session.createdAt()).andReturn(now);
- expect(session.savedAt()).andReturn(now);
- expect(session.attributes()).andReturn(attrs);
-
- Node node = unit.mock(Node.class);
- node.setProperty(isA(String.class), isA(Object.class));
- expectLastCall().anyTimes();
- expect(dbService.findNode(isA(Label.class), isA(String.class), isA(Object.class))).andReturn(null);
- expect(dbService.createNode(isA(Label.class))).andReturn(node);
- };
-
- @SuppressWarnings("unchecked")
- MockUnit.Block getFromSession = unit -> {
- long now = System.currentTimeMillis();
-
- Node node = unit.mock(Node.class);
- expect(node.getAllProperties()).andReturn(properties);
-
- Map sessionMap = unit.constructor(LinkedHashMap.class)
- .args(Map.class).build(properties);
-
- expect(sessionMap.remove("_accessedAt")).andReturn(now);
- expect(sessionMap.remove("_createdAt")).andReturn(now);
- expect(sessionMap.remove("_savedAt")).andReturn(now);
- expect(sessionMap.remove("_id")).andReturn(now);
- expect(sessionMap.remove("_expire")).andReturn(null);
- sessionMap.forEach(unit.capture(BiConsumer.class));
-
- sb = unit.mock(Session.Builder.class);
- expect(sb.sessionId()).andReturn("1234");
- expect(sb.accessedAt(now)).andReturn(sb);
- expect(sb.createdAt(now)).andReturn(sb);
- expect(sb.savedAt(now)).andReturn(sb);
-
- Map.Entry property = properties.entrySet().iterator().next();
- expect(sb.set(property.getKey(), property.getValue().toString())).andReturn(sb);
-
- expect(sb.build()).andReturn(unit.get(Session.class));
- expect(dbService.findNode(isA(Label.class), isA(String.class), isA(Object.class))).andReturn(node);
- };
-
- MockUnit.Block handleTransaction = unit -> {
- Transaction t = unit.mock(Transaction.class);
- t.success();
- expectLastCall();
- t.close();
- expectLastCall();
- expect(dbService.beginTx()).andReturn(t);
- };
-
- @Test
- public void defaults() throws Exception {
- new MockUnit(GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .run(unit -> {
- new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L);
- });
- }
-
- @Test(expected = NullPointerException.class)
- public void defaultsNullDB() throws Exception {
- new EmbeddedNeo4jSessionStore(null, null, "sess", 60L);
- }
-
- @Test
- public void create() throws Exception {
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(saveSession)
- .expect(handleTransaction)
- .run(unit -> {
- new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L)
- .create(unit.get(Session.class));
- });
- }
-
- @Test
- public void save() throws Exception {
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(saveSession)
- .expect(handleTransaction)
- .run(unit -> {
- new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L)
- .save(unit.get(Session.class));
- });
- }
-
- @Test
- public void update() throws Exception {
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(updateSession)
- .expect(handleTransaction)
- .run(unit -> {
- new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L)
- .save(unit.get(Session.class));
- });
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void get() throws Exception {
- properties = Collections.singletonMap("a.b", "c");
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(getFromSession)
- .expect(handleTransaction)
- .run(unit -> {
- EmbeddedNeo4jSessionStore nss = new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L);
- assertEquals(unit.get(Session.class), nss.get(sb));
- }, unit -> {
- BiConsumer setter = unit.captured(BiConsumer.class).get(0);
- setter.accept("a\uFF0Eb", "c");
- });
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void getDollar() throws Exception {
- properties = Collections.singletonMap("$ab", "c");
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(getFromSession)
- .expect(handleTransaction)
- .run(unit -> {
- EmbeddedNeo4jSessionStore nss = new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L);
- assertEquals(unit.get(Session.class), nss.get(sb));
- }, unit -> {
- BiConsumer setter = unit.captured(BiConsumer.class).get(0);
- setter.accept("\uFF04ab", "c");
- });
- }
-
- @Test
- public void getExpired() throws Exception {
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(unit -> {
- sb = unit.mock(Session.Builder.class);
- expect(sb.sessionId()).andReturn("1234");
- expect(dbService.findNode(isA(Label.class), isA(String.class), isA(Object.class))).andReturn(null);
- })
- .expect(unit -> {
- Transaction t = unit.mock(Transaction.class);
- t.close();
- expectLastCall();
- expect(dbService.beginTx()).andReturn(t);
- })
- .run(unit -> {
- EmbeddedNeo4jSessionStore nss = new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L);
- assertEquals(null, nss.get(sb));
- });
- }
-
- @Test
- public void delete() throws Exception {
- new MockUnit(Session.class, GraphDatabaseService.class, GraphAwareRuntime.class, ExpirationModule.class)
- .expect(boot)
- .expect(unit -> {
- Node node = unit.mock(Node.class);
- node.delete();
- expectLastCall();
- expect(dbService.findNode(isA(Label.class), isA(String.class), isA(Object.class))).andReturn(node);
- })
- .expect(handleTransaction)
- .run(unit -> {
- new EmbeddedNeo4jSessionStore(dbService, graphAwareRuntime, "sess", 60L).delete("1234");
- });
- }
-}
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jTest.java b/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jTest.java
deleted file mode 100644
index 3a8bdf20cf..0000000000
--- a/modules/jooby-neo4j/src/test/java/org/jooby/embedded/neo4j/EmbeddedNeo4jTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.jooby.embedded.neo4j;
-
-import com.google.inject.Binder;
-import com.google.inject.Key;
-import com.google.inject.binder.AnnotatedBindingBuilder;
-import com.google.inject.name.Names;
-import com.graphaware.runtime.GraphAwareRuntime;
-import com.graphaware.runtime.GraphAwareRuntimeFactory;
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import com.typesafe.config.ConfigValueFactory;
-import javaslang.control.Try;
-import org.jooby.Env;
-import org.jooby.test.MockUnit;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import java.io.File;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
-import static org.junit.Assert.assertEquals;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({GraphDatabaseService.class, GraphAwareRuntime.class,
- GraphAwareRuntimeFactory.class, GraphDatabaseFactory.class,
- GraphDatabaseBuilder.class, EmbeddedNeo4j.class})
-public class EmbeddedNeo4jTest {
-
- private Config $neo4j = ConfigFactory.parseResources(getClass(), "/embedded/embedded_neo4j.conf");
- private GraphDatabaseService dbService;
- private GraphAwareRuntime graphRuntime;
-
- @SuppressWarnings("unchecked")
- MockUnit.Block neo4j = unit -> {
- dbService = unit.mock(GraphDatabaseService.class);
- unit.registerMock(GraphDatabaseService.class, dbService);
- dbService.shutdown();
- expectLastCall();
-
- GraphDatabaseBuilder graphDatabaseBuilder = unit.mock(GraphDatabaseBuilder.class);
- unit.registerMock(GraphDatabaseBuilder.class, graphDatabaseBuilder);
- expect(graphDatabaseBuilder.newGraphDatabase()).andReturn(dbService);
-
- GraphDatabaseFactory graphDatabaseFactory = unit.mockConstructor(GraphDatabaseFactory.class);
- expect(graphDatabaseFactory.newEmbeddedDatabaseBuilder(isA(File.class))).andReturn(graphDatabaseBuilder);
- unit.registerMock(GraphDatabaseFactory.class, graphDatabaseFactory);
-
- graphRuntime = unit.mock(GraphAwareRuntime.class);
- unit.registerMock(GraphAwareRuntime.class, graphRuntime);
-
- unit.mockStatic(GraphAwareRuntimeFactory.class);
- expect(GraphAwareRuntimeFactory.createRuntime(dbService)).andReturn(graphRuntime);
-
- AnnotatedBindingBuilder dbsABB = unit.mock(AnnotatedBindingBuilder.class);
- dbsABB.toInstance(dbService);
- dbsABB.toInstance(dbService);
-
- AnnotatedBindingBuilder grABB = unit.mock(AnnotatedBindingBuilder.class);
- grABB.toInstance(graphRuntime);
- grABB.toInstance(graphRuntime);
-
- Binder binder = unit.get(Binder.class);
- expect(binder.bind(Key.get(GraphDatabaseService.class))).andReturn(dbsABB);
- expect(binder.bind(Key.get(GraphDatabaseService.class, Names.named("/tmp")))).andReturn(dbsABB);
-
- expect(binder.bind(Key.get(GraphAwareRuntime.class))).andReturn(grABB);
- expect(binder.bind(Key.get(GraphAwareRuntime.class, Names.named("/tmp")))).andReturn(grABB);
-
- Env env = unit.get(Env.class);
- expect(env.onStop(unit.capture(Try.CheckedRunnable.class))).andReturn(env);
- };
-
- @Test
- public void defaults() throws Exception {
- new MockUnit(Config.class, Binder.class, Env.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j")).andReturn(false);
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- expect(dbService.isAvailable(60000L)).andReturn(true);
- })
- .run(unit -> {
- EmbeddedNeo4j embeddedNeo4j = new EmbeddedNeo4j();
- embeddedNeo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- }, unit -> {
- unit.captured(Try.CheckedRunnable.class).iterator().next().run();
- });
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void shouldFailWhenDbIsMissing() throws Exception {
- new MockUnit(Config.class, Binder.class, Env.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j")).andReturn(false);
- })
- .expect(neo4j)
- .expect(unit -> {
- expect(dbService.isAvailable(60000L)).andReturn(false);
- })
- .run(unit -> {
- EmbeddedNeo4j embeddedNeo4j = new EmbeddedNeo4j();
- embeddedNeo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- });
- }
-
- @Test
- public void defaultsWithCustomAction() throws Exception {
- new MockUnit(Config.class, Binder.class, Env.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j")).andReturn(true);
- expect(config.getConfig("neo4j")).andReturn(ConfigFactory.empty()
- .withValue("databaseDir", ConfigValueFactory.fromAnyRef("/tmp")));
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- expect(dbService.isAvailable(60000L)).andReturn(true);
- })
- .run(unit -> {
- new EmbeddedNeo4j()
- .properties((properties, config) -> {
- assertEquals("/tmp", properties.getProperty("databaseDir"));
- })
- .configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- }, unit -> {
- unit.captured(Try.CheckedRunnable.class).iterator().next().run();
- });
- }
-
- @Test
- public void defaultsConfig() throws Exception {
- new MockUnit(Config.class, Binder.class, Env.class)
- .expect(unit -> {
- assertEquals($neo4j, new EmbeddedNeo4j().config());
- });
- }
-
- @Test
- public void defaultsWithProperties() throws Exception {
- new MockUnit(Config.class, Binder.class, Env.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j")).andReturn(false);
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- expect(dbService.isAvailable(60000L)).andReturn(true);
- })
- .run(unit -> {
- new EmbeddedNeo4j()
- .properties((properties, config) -> {
- properties.put("databaseDir", "/tmp");
- })
- .configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- }, unit -> {
- unit.captured(Try.CheckedRunnable.class).iterator().next().run();
- });
- }
-
- private MockUnit.Block serviceKey(final Env.ServiceKey serviceKey) {
- return unit -> {
- Env env = unit.get(Env.class);
- expect(env.serviceKey()).andReturn(serviceKey);
- };
- }
-}
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jSessionStoreTest.java b/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jSessionStoreTest.java
new file mode 100644
index 0000000000..aac6b45af7
--- /dev/null
+++ b/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jSessionStoreTest.java
@@ -0,0 +1,439 @@
+package org.jooby.neo4j;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.jooby.Session;
+import org.jooby.Session.Builder;
+import org.jooby.test.MockUnit;
+import org.jooby.test.MockUnit.Block;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import iot.jcypher.database.IDBAccess;
+import iot.jcypher.graph.GrNode;
+import iot.jcypher.graph.GrProperty;
+import iot.jcypher.query.JcQuery;
+import iot.jcypher.query.JcQueryResult;
+import iot.jcypher.query.api.IClause;
+import iot.jcypher.query.api.modify.ModifyTerminal;
+import iot.jcypher.query.api.modify.Set;
+import iot.jcypher.query.api.pattern.Node;
+import iot.jcypher.query.api.pattern.Property;
+import iot.jcypher.query.api.returns.RSortable;
+import iot.jcypher.query.factories.clause.CREATE;
+import iot.jcypher.query.factories.clause.DO;
+import iot.jcypher.query.factories.clause.MATCH;
+import iot.jcypher.query.factories.clause.RETURN;
+import iot.jcypher.query.values.JcNode;
+import iot.jcypher.query.values.JcProperty;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({Neo4jSessionStore.class, JcQuery.class, JcNode.class, MATCH.class, DO.class,
+ System.class, RETURN.class, CREATE.class })
+public class Neo4jSessionStoreTest {
+
+ @Test
+ public void newStore() throws Exception {
+ new MockUnit(IDBAccess.class)
+ .run(unit -> {
+ new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m");
+ });
+ }
+
+ @Test
+ public void get() throws Exception {
+ new MockUnit(IDBAccess.class, Session.Builder.class)
+ .expect(sessionId("sidfoo"))
+ .expect(newNode("n"))
+ .expect(millis())
+ .expect(GET("sidfoo", "session", TimeUnit.MINUTES.toMillis(30)))
+ .expect(newQuery())
+ .expect(execute())
+ .expect(resultOf())
+ .expect(newSession())
+ .run(unit -> {
+ Session session = new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m")
+ .get(unit.get(Session.Builder.class));
+ assertEquals(unit.get(Session.class), session);
+ });
+ }
+
+ @Test
+ public void getNull() throws Exception {
+ new MockUnit(IDBAccess.class, Session.Builder.class)
+ .expect(sessionId("sidfoo"))
+ .expect(newNode("n"))
+ .expect(millis())
+ .expect(GET("sidfoo", "session", TimeUnit.SECONDS.toMillis(30)))
+ .expect(newQuery())
+ .expect(execute())
+ .expect(emptyResultOf())
+ .run(unit -> {
+ Session session = new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30")
+ .get(unit.get(Session.Builder.class));
+ assertEquals(null, session);
+ });
+ }
+
+ @Test
+ public void save() throws Exception {
+ new MockUnit(IDBAccess.class, Session.class)
+ .expect(sid("sidfoo", ImmutableMap.of("foo", "bar"), 1L, 2L, 3L))
+ .expect(newNode("n"))
+ .expect(millis())
+ .expect(SAVE("sidfoo", "session", 1L, 2L, 3L, TimeUnit.MINUTES.toMillis(30)))
+ .expect(newQuery())
+ .expect(execute())
+ .expect(resultOf())
+ .expect(unit -> {
+ GrProperty foo = unit.mock(GrProperty.class);
+ expect(foo.getName()).andReturn("foo");
+ GrNode node = unit.get(GrNode.class);
+ expect(node.getProperties()).andReturn(ImmutableList.of(foo));
+ })
+ .run(unit -> {
+ new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m")
+ .save(unit.get(Session.class));
+ });
+ }
+
+ @Test
+ public void saveDeleteUnsetProps() throws Exception {
+ new MockUnit(IDBAccess.class, Session.class)
+ .expect(sid("sidfoo", ImmutableMap.of("foo", "bar"), 1L, 2L, 3L))
+ .expect(newNode("n"))
+ .expect(millis())
+ .expect(SAVE("sidfoo", "session", 1L, 2L, 3L, TimeUnit.MINUTES.toMillis(30)))
+ .expect(newQuery())
+ .expect(execute())
+ .expect(resultOf())
+ .expect(unit -> {
+ GrProperty bar = unit.mock(GrProperty.class);
+ expect(bar.getName()).andReturn("bar");
+ GrNode node = unit.get(GrNode.class);
+ expect(node.getProperties()).andReturn(ImmutableList.of(bar));
+ })
+ .expect(newQuery())
+ .expect(REMOVE("sidfoo", "session", "bar"))
+ .expect(execute())
+ .run(unit -> {
+ new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m")
+ .save(unit.get(Session.class));
+ });
+ }
+
+ @Test
+ public void create() throws Exception {
+ new MockUnit(IDBAccess.class, Session.class)
+ .expect(sid("sidfoo", ImmutableMap.of("foo", "bar"), 1L, 2L, 3L))
+ .expect(newNode("n"))
+ .expect(millis())
+ .expect(SAVE("sidfoo", "session", 1L, 2L, 3L, TimeUnit.MINUTES.toMillis(30)))
+ .expect(newQuery())
+ .expect(execute())
+ .expect(emptyResultOf())
+ .expect(newQuery())
+ .expect(CREATE("sidfoo", "session", 1L, 2L, 3L, TimeUnit.MINUTES.toMillis(30)))
+ .expect(execute())
+ .expect(emptyResultOf())
+ .run(unit -> {
+ new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m")
+ .create(unit.get(Session.class));
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void delete() throws Exception {
+ new MockUnit(IDBAccess.class)
+ .expect(newNode("n"))
+ .expect(unit -> {
+ {
+ unit.mockStatic(MATCH.class);
+
+ Node node = unit.mock(Node.class);
+
+ Property prop = unit.mock(Property.class);
+ expect(prop.value("sidfoo")).andReturn(node);
+
+ expect(node.label("session")).andReturn(node);
+ expect(node.property("_id")).andReturn(prop);
+ expect(MATCH.node(unit.get(JcNode.class))).andReturn(node);
+ }
+
+ {
+ unit.mockStatic(DO.class);
+ JcNode node = unit.get(JcNode.class);
+ expect(DO.DELETE(node)).andReturn(null);
+ }
+ })
+ .expect(newQuery())
+ .expect(execute())
+ .run(unit -> {
+ new Neo4jSessionStore(unit.get(IDBAccess.class), "session", "30m")
+ .delete("sidfoo");
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block CREATE(final String sid, final String label, final long accessedAt,
+ final long createdAt, final long savedAt, final long millis) {
+ return unit -> {
+ {
+ unit.mockStatic(CREATE.class);
+
+ Node node = unit.mock(Node.class);
+
+ Property id = unit.mock(Property.class);
+ expect(id.value(sid)).andReturn(node);
+
+ Property _accessedAt = unit.mock(Property.class);
+ expect(_accessedAt.value(accessedAt)).andReturn(node);
+
+ Property _savedAt = unit.mock(Property.class);
+ expect(_savedAt.value(savedAt)).andReturn(node);
+
+ Property _createdAt = unit.mock(Property.class);
+ expect(_createdAt.value(createdAt)).andReturn(node);
+
+ Property _expire = unit.mock(Property.class);
+ expect(_expire.value(millis)).andReturn(node);
+
+ Property _foo = unit.mock(Property.class);
+ expect(_foo.value("bar")).andReturn(node);
+
+ expect(node.label(label)).andReturn(node);
+ expect(node.property("_id")).andReturn(id);
+ expect(node.property("_accessedAt")).andReturn(_accessedAt);
+ expect(node.property("_savedAt")).andReturn(_savedAt);
+ expect(node.property("_createdAt")).andReturn(_createdAt);
+ expect(node.property("_expire")).andReturn(_expire);
+ expect(node.property("foo")).andReturn(_foo);
+ expect(CREATE.node(unit.get(JcNode.class))).andReturn(node);
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block SAVE(final String sid, final String label, final long accessedAt,
+ final long createdAt, final long savedAt, final long timeout) {
+ return unit -> {
+ {
+ unit.mockStatic(MATCH.class);
+
+ Node node = unit.mock(Node.class);
+
+ Property prop = unit.mock(Property.class);
+ expect(prop.value(sid)).andReturn(node);
+
+ expect(node.label(label)).andReturn(node);
+ expect(node.property("_id")).andReturn(prop);
+ expect(MATCH.node(unit.get(JcNode.class))).andReturn(node);
+ }
+
+ DO_SET(unit, "_accessedAt", accessedAt);
+ DO_SET(unit, "_createdAt", createdAt);
+ DO_SET(unit, "_savedAt", savedAt);
+ DO_SET(unit, "_expire", timeout);
+ DO_SET(unit, "foo", "bar");
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private void DO_SET(final MockUnit unit, final String name, final Object value) {
+ unit.mockStatic(DO.class);
+
+ JcProperty prop = unit.mock(JcProperty.class);
+ JcNode node = unit.get(JcNode.class);
+ expect(node.property(name)).andReturn(prop);
+
+ Set mod = unit.mock(Set.class);
+ expect(mod.to(value)).andReturn(null);
+
+ expect(DO.SET(prop)).andReturn(mod);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block GET(final String sid, final String label, final long timeout) {
+ return unit -> {
+ {
+ unit.mockStatic(MATCH.class);
+
+ Node node = unit.mock(Node.class);
+
+ Property prop = unit.mock(Property.class);
+ expect(prop.value(sid)).andReturn(node);
+
+ expect(node.label(label)).andReturn(node);
+ expect(node.property("_id")).andReturn(prop);
+ expect(MATCH.node(unit.get(JcNode.class))).andReturn(node);
+ }
+
+ {
+ unit.mockStatic(DO.class);
+
+ JcNode node = unit.get(JcNode.class);
+
+ Set setprop = unit.mock(Set.class);
+ expect(setprop.to(timeout))
+ .andReturn(unit.registerMock(ModifyTerminal.class));
+
+ JcProperty prop = unit.mock(JcProperty.class);
+ expect(node.property("_expire")).andReturn(prop);
+ expect(DO.SET(prop)).andReturn(setprop);
+ }
+
+ {
+ unit.mockStatic(RETURN.class);
+ expect(RETURN.value(unit.get(JcNode.class)))
+ .andReturn(unit.registerMock(RSortable.class));
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block REMOVE(final String sid, final String label, final String property) {
+ return unit -> {
+ {
+ unit.mockStatic(MATCH.class);
+
+ Node node = unit.mock(Node.class);
+
+ Property prop = unit.mock(Property.class);
+ expect(prop.value(sid)).andReturn(node);
+
+ expect(node.label(label)).andReturn(node);
+ expect(node.property("_id")).andReturn(prop);
+ expect(MATCH.node(unit.get(JcNode.class))).andReturn(node);
+ }
+
+ {
+ unit.mockStatic(DO.class);
+
+ JcProperty prop = unit.mock(JcProperty.class);
+
+ JcNode node = unit.get(JcNode.class);
+ expect(node.property(property)).andReturn(prop);
+
+ expect(DO.REMOVE(prop)).andReturn(unit.mock(ModifyTerminal.class));
+ }
+
+ {
+ unit.mockStatic(RETURN.class);
+ expect(RETURN.value(unit.get(JcNode.class)))
+ .andReturn(unit.registerMock(RSortable.class));
+ }
+ };
+ }
+
+ private Block newSession() {
+ return unit -> {
+ Builder builder = unit.get(Session.Builder.class);
+
+ GrProperty accessedAt = unit.mock(GrProperty.class);
+ expect(accessedAt.getValue()).andReturn(1L);
+ expect(builder.accessedAt(1L)).andReturn(builder);
+
+ GrProperty createdAt = unit.mock(GrProperty.class);
+ expect(createdAt.getValue()).andReturn(2L);
+ expect(builder.createdAt(2L)).andReturn(builder);
+
+ GrProperty savedAt = unit.mock(GrProperty.class);
+ expect(savedAt.getValue()).andReturn(3L);
+ expect(builder.savedAt(3L)).andReturn(builder);
+
+ GrProperty foo = unit.mock(GrProperty.class);
+ expect(foo.getName()).andReturn("foo").times(2);
+ expect(foo.getValue()).andReturn("bar");
+ expect(builder.set("foo", "bar")).andReturn(builder);
+
+ GrProperty sid = unit.mock(GrProperty.class);
+ expect(sid.getName()).andReturn("_id");
+
+ GrNode node = unit.get(GrNode.class);
+ expect(node.getProperty("_accessedAt")).andReturn(accessedAt);
+ expect(node.getProperty("_createdAt")).andReturn(createdAt);
+ expect(node.getProperty("_savedAt")).andReturn(savedAt);
+
+ expect(node.getProperties()).andReturn(ImmutableList.of(foo, sid));
+
+ expect(builder.build()).andReturn(unit.registerMock(Session.class));
+ };
+ }
+
+ private Block resultOf() {
+ return unit -> {
+ GrNode node = unit.registerMock(GrNode.class);
+ JcQueryResult result = unit.get(JcQueryResult.class);
+ expect(result.resultOf(unit.get(JcNode.class))).andReturn(ImmutableList.of(node));
+ };
+ }
+
+ private Block emptyResultOf() {
+ return unit -> {
+ JcQueryResult result = unit.get(JcQueryResult.class);
+ expect(result.resultOf(unit.get(JcNode.class))).andReturn(ImmutableList.of());
+ };
+ }
+
+ private Block millis() {
+ return unit -> {
+ unit.mockStatic(System.class);
+ expect(System.currentTimeMillis()).andReturn(0L);
+ };
+ }
+
+ private Block newNode(final String name) {
+ return unit -> {
+ JcNode node = unit.constructor(JcNode.class)
+ .build(name);
+ unit.registerMock(JcNode.class, node);
+ };
+ }
+
+ private Block execute() {
+ return unit -> {
+ JcQueryResult result = unit.registerMock(JcQueryResult.class);
+ IDBAccess db = unit.get(IDBAccess.class);
+ expect(db.execute(unit.get(JcQuery.class))).andReturn(result);
+ };
+ }
+
+ private Block newQuery() {
+ return unit -> {
+ JcQuery query = unit.constructor(JcQuery.class)
+ .build();
+ query.setClauses(unit.capture(IClause[].class));
+ unit.registerMock(JcQuery.class, query);
+ };
+ }
+
+ private Block sessionId(final String sid) {
+ return unit -> {
+ Builder builder = unit.get(Session.Builder.class);
+ expect(builder.sessionId()).andReturn(sid);
+ };
+ }
+
+ private Block sid(final String sid, final Map attrs, final long accessedAt,
+ final long createdAt, final long savedAt) {
+ return unit -> {
+ Session session = unit.get(Session.class);
+ expect(session.id()).andReturn(sid);
+ expect(session.attributes()).andReturn(attrs);
+
+ expect(session.accessedAt()).andReturn(accessedAt);
+ expect(session.createdAt()).andReturn(createdAt);
+ expect(session.savedAt()).andReturn(savedAt);
+ };
+ }
+}
diff --git a/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jTest.java b/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jTest.java
index 670599f896..d85b10085e 100644
--- a/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jTest.java
+++ b/modules/jooby-neo4j/src/test/java/org/jooby/neo4j/Neo4jTest.java
@@ -1,171 +1,586 @@
package org.jooby.neo4j;
-import com.google.inject.Binder;
-import com.google.inject.Key;
-import com.google.inject.binder.AnnotatedBindingBuilder;
-import com.google.inject.name.Names;
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import com.typesafe.config.ConfigValueFactory;
-import iot.jcypher.database.DBAccessFactory;
-import iot.jcypher.database.DBProperties;
-import iot.jcypher.database.DBType;
-import iot.jcypher.database.remote.BoltDBAccess;
-import javaslang.control.Try;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.junit.Assert.assertEquals;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
import org.jooby.Env;
+import org.jooby.Env.ServiceKey;
import org.jooby.test.MockUnit;
+import org.jooby.test.MockUnit.Block;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.neo4j.driver.v1.AuthToken;
+import org.neo4j.driver.v1.AuthTokens;
+import org.neo4j.driver.v1.Driver;
+import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
-import org.neo4j.driver.v1.exceptions.ClientException;
-import org.powermock.api.easymock.PowerMock;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
+import org.neo4j.graphdb.factory.GraphDatabaseFactory;
+import org.neo4j.logging.slf4j.Slf4jLogProvider;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
-import java.util.Properties;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.graphaware.neo4j.expire.ExpirationModuleBootstrapper;
+import com.graphaware.runtime.RuntimeRegistry;
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigException;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigValueFactory;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.isA;
-import static org.junit.Assert.assertEquals;
-import static org.powermock.api.easymock.PowerMock.replayAll;
+import iot.jcypher.database.DBAccessFactory;
+import iot.jcypher.database.DBProperties;
+import iot.jcypher.database.IDBAccess;
+import iot.jcypher.database.embedded.EmbeddedDBAccess;
+import iot.jcypher.database.remote.BoltDBAccess;
+import javaslang.control.Try.CheckedRunnable;
@RunWith(PowerMockRunner.class)
-@PrepareForTest({BoltDBAccess.class, DBAccessFactory.class})
+@PrepareForTest({Neo4j.class, BoltDBAccess.class, DBAccessFactory.class, Properties.class,
+ GraphDatabaseFactory.class, RuntimeRegistry.class, EmbeddedDBAccess.class, GraphDatabase.class,
+ AuthTokens.class })
public class Neo4jTest {
- private Config $neo4j = ConfigFactory.parseResources(getClass(), "/neo4j/neo4j.conf");
- private BoltDBAccess remoteClient;
+ @Test(expected = ConfigException.Missing.class)
+ public void missingDatabase() throws Exception {
+ new MockUnit(Env.class, Config.class, Binder.class)
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", false))
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ });
+ }
- @SuppressWarnings("unchecked")
- MockUnit.Block neo4j = unit -> {
+ @Test
+ public void config() throws Exception {
+ assertEquals(ConfigFactory.empty(getClass().getName().toLowerCase() + ".conf")
+ .withValue("neo4j.session.label", ConfigValueFactory.fromAnyRef("session")),
+ new Neo4j().config());
+ }
- remoteClient = unit.mock(BoltDBAccess.class);
- unit.registerMock(BoltDBAccess.class, remoteClient);
+ @Test
+ public void rm() throws Exception {
+ Path dir = Paths.get("target", "foo");
+ Neo4j.rm(dir);
+ Files.createDirectories(dir);
+ Files.createFile(dir.resolve("foo.txt"));
+ Path subdir = dir.resolve("bar");
+ Files.createDirectories(subdir);
+ Files.createFile(subdir.resolve("bar.txt"));
- AnnotatedBindingBuilder rcABB = unit.mock(AnnotatedBindingBuilder.class);
- rcABB.toInstance(remoteClient);
- rcABB.toInstance(remoteClient);
+ assertEquals(true, Files.exists(dir));
+ Neo4j.rm(dir);
+ assertEquals(false, Files.exists(dir));
+ Neo4j.rm(dir);
+ assertEquals(false, Files.exists(dir));
+ }
- Binder binder = unit.get(Binder.class);
- expect(binder.bind(Key.get(BoltDBAccess.class))).andReturn(rcABB);
- expect(binder.bind(Key.get(BoltDBAccess.class, Names.named("bolt://localhost:7687")))).andReturn(rcABB);
+ @Test
+ public void memDirect() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jmem").toAbsolutePath();
+ new MockUnit(Env.class, Config.class, Binder.class)
+ .expect(hasPath("mem.url", false))
+ .expect(hasPath("mem", false))
+ .expect(hasPath("mem", false))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("neo4j.mem", false))
+ .expect(confString("application.tmpdir", dir.toString()))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "mem"))
+ .expect(embeddedAccess("mem"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j("mem");
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
+ }
- Env env = unit.get(Env.class);
- expect(env.onStop(unit.capture(Try.CheckedRunnable.class))).andReturn(env);
- };
+ @SuppressWarnings({"unchecked", "rawtypes" })
+ private Block bind(final Class class1, final int i) {
+ return unit -> {
+ List consumers = unit.captured(Consumer.class);
+ consumers.get(i).accept(Key.get(class1));
+ };
+ }
@Test
- public void defaults() throws Exception {
+ public void memAsProperty() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jmem").toAbsolutePath();
new MockUnit(Env.class, Config.class, Binder.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j.db")).andReturn(false);
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- PowerMock.mockStatic(DBAccessFactory.class);
- expect(DBAccessFactory.createDBAccess(isA(DBType.class), isA(Properties.class),
- isA(String.class), isA(String.class))).andReturn(remoteClient);
- replayAll();
- expect(remoteClient.getSession()).andReturn(unit.registerMock(Session.class));
- })
- .expect(unit -> {
- BoltDBAccess remoteClient = unit.get(BoltDBAccess.class);
- remoteClient.close();
- })
- .run(unit -> {
- Neo4j neo4j = new Neo4j();
- neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- }, unit -> {
- unit.captured(Try.CheckedRunnable.class).iterator().next().run();
- });
- }
-
- @Test(expected = ClientException.class)
- public void shouldFailWhenDbIsMissing() throws Exception {
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", true))
+ .expect(confString("db", "mem"))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("db", true))
+ .expect(notAConf("db"))
+ .expect(hasPath("neo4j.db", false))
+ .expect(confString("application.tmpdir", dir.toString()))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "db"))
+ .expect(embeddedAccess("db"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
+ }
+
+ @Test
+ public void bolt() throws Exception {
new MockUnit(Env.class, Config.class, Binder.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j.db")).andReturn(false);
- expect(config.getString("server_root_uri")).andReturn("bolt://localhost:7687");
- })
- .expect(neo4j)
- .run(unit -> {
- Neo4j neo4j = new Neo4j();
- neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- });
+ .expect(hasPath("db.url", true))
+ .expect(confString("db.url", "bolt://localhost:7687"))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("db", true))
+ .expect(confConf("db", ConfigFactory.empty()))
+ .expect(hasPath("neo4j.db", false))
+ .expect(serviceKey())
+ .expect(confString("db.user", "test"))
+ .expect(confString("db.password", "test"))
+ .expect(bolt("bolt://localhost:7687", "db", "test", "test"))
+ .expect(props())
+ .expect(setProp("server_root_uri", "bolt://localhost:7687"))
+ .expect(boltAccess("db"))
+ .expect(logdb("bolt://localhost:7687", null))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(Driver.class, 0),
+ bind(Session.class, 1));
}
@Test
- public void defaultsWithCustomAction() throws Exception {
+ public void customConnection() throws Exception {
new MockUnit(Env.class, Config.class, Binder.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j"))
- .andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j.db")).andReturn(true);
- expect(config.getConfig("neo4j.db")).andReturn(ConfigFactory.empty()
- .withValue("server_root_uri", ConfigValueFactory.fromAnyRef("bolt://localhost:7687")));
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- PowerMock.mockStatic(DBAccessFactory.class);
- expect(DBAccessFactory.createDBAccess(isA(DBType.class), isA(Properties.class),
- isA(String.class), isA(String.class))).andReturn(remoteClient);
- replayAll();
- expect(remoteClient.getSession()).andReturn(unit.registerMock(Session.class));
- })
- .run(unit -> {
- new Neo4j()
- .properties((properties, config) -> {
- assertEquals("bolt://localhost:7687", properties.getProperty(DBProperties.SERVER_ROOT_URI));
- })
- .configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- });
+ .expect(hasPath("mydb.url", true))
+ .expect(confString("mydb.url", "bolt://localhost:7687"))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("mydb", true))
+ .expect(confConf("mydb", ConfigFactory.empty()))
+ .expect(hasPath("neo4j.mydb", false))
+ .expect(serviceKey())
+ .expect(confString("mydb.user", "test"))
+ .expect(confString("mydb.password", "test"))
+ .expect(bolt("bolt://localhost:7687", "mydb", "test", "test"))
+ .expect(props())
+ .expect(setProp("server_root_uri", "bolt://localhost:7687"))
+ .expect(boltAccess("mydb"))
+ .expect(logdb("bolt://localhost:7687", null))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j("mydb");
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(Driver.class, 0),
+ bind(Session.class, 1));
}
@Test
- public void defaultsConfig() throws Exception {
+ public void fs() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jfs").toAbsolutePath();
new MockUnit(Env.class, Config.class, Binder.class)
- .expect(unit -> {
- assertEquals($neo4j, new Neo4j().config());
- });
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", true))
+ .expect(confString("db", "fs"))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("db", true))
+ .expect(notAConf("db"))
+ .expect(hasPath("neo4j.db", false))
+ .expect(confString("application.tmpdir", dir.toString()))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "db"))
+ .expect(embeddedAccess("db"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
}
@Test
- public void defaultsWithProperties() throws Exception {
+ public void fspath() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("dbdir").toAbsolutePath();
new MockUnit(Env.class, Config.class, Binder.class)
- .expect(unit -> {
- Config config = unit.get(Config.class);
- expect(config.getConfig("neo4j")).andReturn($neo4j.getConfig("neo4j"));
- expect(config.hasPath("neo4j.db")).andReturn(false);
- })
- .expect(serviceKey(new Env.ServiceKey()))
- .expect(neo4j)
- .expect(unit -> {
- PowerMock.mockStatic(DBAccessFactory.class);
- expect(DBAccessFactory.createDBAccess(isA(DBType.class), isA(Properties.class),
- isA(String.class), isA(String.class))).andReturn(remoteClient);
- replayAll();
- expect(remoteClient.getSession()).andReturn(unit.registerMock(Session.class));
- })
- .run(unit -> {
- new Neo4j()
- .properties((properties, config) -> {
- properties.put(DBProperties.SERVER_ROOT_URI, "bolt://localhost:7687");
- })
- .configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
- });
- }
-
- private MockUnit.Block serviceKey(final Env.ServiceKey serviceKey) {
+ .expect(hasPath(dbdir + ".url", false))
+ .expect(hasPath(dbdir.toString(), false))
+ .expect(hasPath(dbdir.toString(), false))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("neo4j." + dbdir.toString(), false))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, dbdir.toString()))
+ .expect(embeddedAccess(dbdir.toString()))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j(dbdir);
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
+ }
+
+ @Test
+ public void oneModule() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jfs").toAbsolutePath();
+ new MockUnit(Env.class, Config.class, Binder.class)
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", true))
+ .expect(confString("db", dbdir.toString()))
+ .expect(hasPath("com.graphaware", true))
+ .expect(confConf("com.graphaware",
+ ConfigFactory.empty().withValue("module",
+ ConfigValueFactory.fromAnyRef(
+ (ImmutableMap.of("class", ExpirationModuleBootstrapper.class.getName(),
+ "nodeExpirationProperty", "_expire"))))))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("db", false))
+ .expect(hasPath("neo4j.db", false))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(putProp("com.graphaware.module.m1.1", ExpirationModuleBootstrapper.class.getName()))
+ .expect(putProp("com.graphaware.module.m1.nodeExpirationProperty", "_expire"))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "db"))
+ .expect(embeddedAccess("db"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
+ }
+
+ @Test
+ public void multipleModule() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jfs").toAbsolutePath();
+ new MockUnit(Env.class, Config.class, Binder.class)
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", true))
+ .expect(confString("db", dbdir.toString()))
+ .expect(hasPath("com.graphaware", true))
+ .expect(confConf("com.graphaware",
+ ConfigFactory.empty().withValue("module",
+ ConfigValueFactory.fromAnyRef(Arrays.asList(
+ (ImmutableMap.of("class", ExpirationModuleBootstrapper.class.getName(),
+ "nodeExpirationProperty", "_expire")),
+ (ImmutableMap.of("class", "com.foo.Foo",
+ "foo", "bar")))))))
+ .expect(hasPath("neo4j", false))
+ .expect(hasPath("db", false))
+ .expect(hasPath("neo4j.db", false))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(putProp("com.graphaware.module.m1.1", ExpirationModuleBootstrapper.class.getName()))
+ .expect(putProp("com.graphaware.module.m1.nodeExpirationProperty", "_expire"))
+ .expect(putProp("com.graphaware.module.m2.2", "com.foo.Foo"))
+ .expect(putProp("com.graphaware.module.m2.foo", "bar"))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "db"))
+ .expect(embeddedAccess("db"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ });
+ }
+
+ @SuppressWarnings({"unchecked", "deprecation" })
+ @Test
+ public void embedded() throws Exception {
+ Path dir = Paths.get("target", "des").toAbsolutePath();
+ Path dbdir = dir.resolve("neo4jfs").toAbsolutePath();
+ new MockUnit(Env.class, Config.class, Binder.class)
+ .expect(hasPath("db.url", false))
+ .expect(hasPath("db", true))
+ .expect(confString("db", dbdir.toString()))
+ .expect(hasPath("com.graphaware", false))
+ .expect(hasPath("neo4j", true))
+ .expect(confConf("neo4j",
+ ConfigFactory.empty().withValue("unsupported.dbms.block_size.array_properties",
+ ConfigValueFactory.fromAnyRef(120))))
+ .expect(hasPath("db", false))
+ .expect(hasPath("neo4j.db", false))
+ .expect(props())
+ .expect(setProp("database_dir", dbdir.toString()))
+ .expect(putProp("unsupported.dbms.block_size.array_properties", 120))
+ .expect(serviceKey())
+ .expect(dbFactory(dbdir, "db"))
+ .expect(embeddedAccess("db"))
+ .expect(logdb(null, dbdir.toString()))
+ .expect(onStop())
+ .expect(unit -> {
+ GraphDatabaseBuilder builder = unit.get(GraphDatabaseBuilder.class);
+ expect(builder.setConfig("unsupported.dbms.block_size.array_properties", "120"))
+ .andReturn(builder);
+ })
+ .run(unit -> {
+ Neo4j neo4j = new Neo4j();
+ neo4j.configure(unit.get(Env.class), unit.get(Config.class), unit.get(Binder.class));
+ }, closeOnStop(),
+ bind(GraphDatabaseService.class, 0),
+ bind(IDBAccess.class, 1),
+ unit -> {
+ IDBAccess db = unit.get(IDBAccess.class);
+ bind(db.getClass(), 2).run(unit);
+ }, unit -> {
+ unit.captured(BiConsumer.class).get(0)
+ .accept("unsupported.dbms.block_size.array_properties", "120");
+ });
+ }
+
+ private Block closeOnStop() {
+ return unit -> {
+ unit.captured(CheckedRunnable.class).get(0).run();
+ };
+ }
+
+ private Block onStop() {
+ return unit -> {
+ Env env = unit.get(Env.class);
+ unit.get(IDBAccess.class).close();
+ expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env);
+ };
+ }
+
+ private Block logdb(final String uri, final String dir) {
+ return unit -> {
+ Properties props = unit.get(Properties.class);
+ expect(props.getProperty(DBProperties.SERVER_ROOT_URI)).andReturn(uri);
+ expect(props.getProperty(DBProperties.DATABASE_DIR)).andReturn(dir);
+ };
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes" })
+ private Block embeddedAccess(final String dbkey) {
+ return unit -> {
+ EmbeddedDBAccess db = unit.constructor(EmbeddedDBAccess.class)
+ .build();
+ unit.registerMock(IDBAccess.class, db);
+ db.initialize(unit.get(Properties.class));
+
+ LinkedBindingBuilder lbb = unit.mock(LinkedBindingBuilder.class);
+ lbb.toInstance(db);
+ lbb.toInstance(db);
+
+ Binder binder = unit.get(Binder.class);
+ expect(binder.bind(Key.get(IDBAccess.class))).andReturn(lbb);
+ expect(binder.bind(Key.get(db.getClass()))).andReturn(lbb);
+
+ ServiceKey keys = unit.get(ServiceKey.class);
+ keys.generate(eq(IDBAccess.class), eq(dbkey), unit.capture(Consumer.class));
+ keys.generate(eq(db.getClass()), eq(dbkey), unit.capture(Consumer.class));
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block boltAccess(final String dbkey) {
+ return unit -> {
+ BoltDBAccess db = unit.constructor(BoltDBAccess.class)
+ .build();
+ unit.registerMock(IDBAccess.class, db);
+ db.initialize(unit.get(Properties.class));
+
+ ServiceKey keys = unit.get(ServiceKey.class);
+ keys.generate(eq(IDBAccess.class), eq(dbkey), unit.capture(Consumer.class));
+ keys.generate(eq(db.getClass()), eq(dbkey), unit.capture(Consumer.class));
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block dbFactory(final Path dbdir, final String dbkey) {
+ return unit -> {
+ GraphDatabaseService dbservice = unit.registerMock(GraphDatabaseService.class);
+ // unit.mockStatic(RuntimeRegistry.class);
+ // expect(RuntimeRegistry.getStartedRuntime(dbservice)).andReturn(null);
+
+ LinkedBindingBuilder lbb = unit.mock(LinkedBindingBuilder.class);
+ lbb.toInstance(dbservice);
+
+ Binder binder = unit.get(Binder.class);
+ expect(binder.bind(Key.get(GraphDatabaseService.class))).andReturn(lbb);
+
+ ServiceKey keys = unit.get(ServiceKey.class);
+ keys.generate(eq(GraphDatabaseService.class), eq(dbkey), unit.capture(Consumer.class));
+
+ GraphDatabaseBuilder dbbuilder = unit.registerMock(GraphDatabaseBuilder.class);
+ expect(dbbuilder.newGraphDatabase()).andReturn(dbservice);
+
+ GraphDatabaseFactory factory = unit.constructor(GraphDatabaseFactory.class)
+ .build();
+ expect(factory.setUserLogProvider(isA(Slf4jLogProvider.class))).andReturn(factory);
+ expect(factory.newEmbeddedDatabaseBuilder(dbdir.toFile())).andReturn(dbbuilder);
+ };
+ }
+
+ private Block setProp(final String key, final String value) {
return unit -> {
+ Properties props = unit.get(Properties.class);
+ expect(props.setProperty(key, value)).andReturn(null);
+ };
+ }
+
+ private Block putProp(final String key, final Object value) {
+ return unit -> {
+ Properties props = unit.get(Properties.class);
+ expect(props.put(key, value)).andReturn(null);
+ };
+ }
+
+ private Block serviceKey() {
+ return unit -> {
+ ServiceKey keys = unit.registerMock(Env.ServiceKey.class);
Env env = unit.get(Env.class);
- expect(env.serviceKey()).andReturn(serviceKey);
+ expect(env.serviceKey()).andReturn(keys);
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ private Block props() {
+ return unit -> {
+ Properties props = unit.constructor(Properties.class)
+ .build();
+ props.forEach(unit.capture(BiConsumer.class));
+ expectLastCall().times(0, 1);
+ unit.registerMock(Properties.class, props);
+ };
+ }
+
+ private Block notAConf(final String path) {
+ return unit -> {
+ Config conf = unit.get(Config.class);
+ expect(conf.getConfig(path))
+ .andThrow(new ConfigException.WrongType(ConfigFactory.empty().origin(), path));
+ };
+ }
+
+ private Block confString(final String path, final String value) {
+ return unit -> {
+ Config conf = unit.get(Config.class);
+ expect(conf.getString(path)).andReturn(value);
+ };
+ }
+
+ private Block hasPath(final String path, final boolean value) {
+ return unit -> {
+ Config conf = unit.get(Config.class);
+ expect(conf.hasPath(path)).andReturn(value);
+ };
+ }
+
+ private Block confConf(final String path, final Config value) {
+ return unit -> {
+ Config conf = unit.get(Config.class);
+ expect(conf.getConfig(path)).andReturn(value);
+ };
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes" })
+ private Block bolt(final String uri, final String dbkey, final String user, final String pass) {
+ return unit -> {
+ AuthToken token = unit.mock(AuthToken.class);
+
+ unit.mockStatic(AuthTokens.class);
+ expect(AuthTokens.basic(user, pass)).andReturn(token);
+
+ Binder binder = unit.get(Binder.class);
+
+ Session session = unit.registerMock(Session.class);
+
+ LinkedBindingBuilder lbbs = unit.mock(LinkedBindingBuilder.class);
+ lbbs.toInstance(session);
+ expect(binder.bind(Key.get(Session.class))).andReturn(lbbs);
+
+ Driver driver = unit.registerMock(Driver.class);
+ expect(driver.session()).andReturn(session);
+
+ LinkedBindingBuilder lbb = unit.mock(LinkedBindingBuilder.class);
+ lbb.toInstance(driver);
+
+ expect(binder.bind(Key.get(Driver.class))).andReturn(lbb);
+
+ unit.mockStatic(GraphDatabase.class);
+ expect(GraphDatabase.driver(uri, token)).andReturn(driver);
+
+ ServiceKey keys = unit.get(ServiceKey.class);
+ keys.generate(eq(Driver.class), eq(dbkey), unit.capture(Consumer.class));
+ keys.generate(eq(Session.class), eq(dbkey), unit.capture(Consumer.class));
};
}
-}
\ No newline at end of file
+}
diff --git a/modules/jooby-neo4j/src/test/resources/embedded/application.conf b/modules/jooby-neo4j/src/test/resources/embedded/application.conf
deleted file mode 100644
index a5008c711b..0000000000
--- a/modules/jooby-neo4j/src/test/resources/embedded/application.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-###################################################################################################
-# neo4j
-###################################################################################################
-neo4j.databaseDir = "C:/Users/i076326/Documents/programs/neo4j_db"
-neo4j.session.label = "sample_app_session"
-session.timeout = "1m"
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/test/resources/embedded/embedded_neo4j.conf b/modules/jooby-neo4j/src/test/resources/embedded/embedded_neo4j.conf
deleted file mode 100644
index 753b9d1d28..0000000000
--- a/modules/jooby-neo4j/src/test/resources/embedded/embedded_neo4j.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-###################################################################################################
-# neo4j
-###################################################################################################
-neo4j.databaseDir = "/tmp"
\ No newline at end of file
diff --git a/modules/jooby-neo4j/src/test/resources/neo4j/neo4j.conf b/modules/jooby-neo4j/src/test/resources/neo4j/neo4j.conf
deleted file mode 100644
index b256ec7509..0000000000
--- a/modules/jooby-neo4j/src/test/resources/neo4j/neo4j.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-###################################################################################################
-# neo4j
-###################################################################################################
-neo4j.server_root_uri = "bolt://localhost:7687"
-neo4j.array_block_size = "120"
-neo4j.pagecache_memory = "1M"
-neo4j.string_block_size = "120"
-neo4j.username = "****"
-neo4j.password = "****"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 12248a2aaa..5e3a7b9caa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -292,6 +292,12 @@
${jooby.version}
+
+ org.jooby
+ jooby-neo4j
+ ${jooby.version}
+
+
org.jooby
jooby-assets
@@ -1540,6 +1546,53 @@
${consul.version}
+
+
+ com.graphaware.neo4j
+ runtime
+ ${neo4j.runtime.version}
+
+
+
+ org.neo4j
+ neo4j-graphdb-api
+ ${neo4j.version}
+
+
+
+ org.neo4j
+ neo4j
+ ${neo4j.version}
+
+
+
+ org.neo4j
+ neo4j-slf4j
+ ${neo4j.version}
+
+
+
+ com.graphaware.neo4j
+ expire
+ ${neo4j.expire.version}
+
+
+
+ net.iot-solutions.graphdb
+ jcypher
+ ${jcypher.version}
+
+
+ org.neo4j
+ neo4j-kernel
+
+
+ org.neo4j
+ neo4j-io
+
+
+
+
junit
@@ -2957,6 +3010,10 @@ org.eclipse.jdt.apt.processorOptions/defaultOverwrite=true
0.16.0
1.1.2-5
1.2.0
+ 3.2.1.51
+ 3.2.1.51.4
+ 3.2.1
+ 3.7.0
**