class file for com.mongodb.ServerAddress not found - java

Trying for a "hello world" of sorts from mongo and Java but I cannot build my project.
I downloaded mongo java lib from here:
https://oss.sonatype.org/content/repositories/releases/org/mongodb/mongodb-driver/3.0.0/
On the below code I get the following error when building:
error: cannot access ServerAddress
Mongo mongo = new Mongo("localhost", 27017);
class file for com.mongodb.ServerAddress not found
Now, the localhost is on 27017 as it is working perfectly via python and pymongo.
I am adapting some old java code that was inserting into a mysql db, but I think mongo is a much better solution.
Thank you so much for any help.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
public class my_mongo_test {
/**
* #param args
* the command line arguments
*/
public static void main(String[] args) {
HashMap<String,String> test = new HashMap<String,String>();
test.put("A","A");
mongo_test(test);
}
public static void mongo_test(HashMap<String,String> arg){
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("testDB");
DBCollection col = db.getCollection("testColl");
DBObject opt = createDBObject(arg);
}
private static DBObject createDBObject(HashMap<String,String> arg) {
BasicDBObjectBuilder docBuilder = BasicDBObjectBuilder.start();
for(String s : arg.keySet()){
docBuilder.append(s, arg.get(s));
}
return docBuilder.get();
}
}

mongodb-driver has multiple dependencies (bson and mongodb-driver-core) so you need more than just the mongodb-driver.jar for it to work. You can use the uber jar mongodb-java-driver that contains all the required dependencies.
I recently updated the installation-guide to add links to the dependencies in the documentation.
I also just create a mongodb java quickstart github repo that has gradle configs and a basic QuickStart.java file to help you get up and running!

Related

Load neo4j dump in test container during integration test run

I am trying to write integration test for neo4j using spring boot. I am using test container. Can anyone help me how to load database dump file to testcontainer?
here's one way to do this (using current Neo4j 5.3). I have a dump file called neo4j.dump created from a local instance and I use withCopyFileToContainer to copy it to the container before it starts.
As I use the community edition in this example, there is no online backup/restore, but only dump/load. So therefor I have to change the startup command. The load needs to happen before Neo4j starts. I can't stop Neo4j in the container because it would stop the container.
Therefor I create a small shell script that executes the desired other command and than delegates to the original entry point.
This script is transferred with file mode 0100555, corresponding to r-xr-xr-x so that it is executable.
Finally, the container is started with the above script as command.
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.utility.MountableFile;
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class LoadDumpTest {
Neo4jContainer<?> neo4j;
Driver driver;
#BeforeAll
void initNeo4j() {
neo4j = new Neo4jContainer<>("neo4j:5.3.0")
.withCopyFileToContainer(MountableFile.forClasspathResource("neo4j.dump"),
"/var/lib/neo4j/data/dumps/neo4j.dump")
.withCopyToContainer(Transferable.of("""
#!/bin/bash -eu
/var/lib/neo4j/bin/neo4j-admin database load neo4j
/startup/docker-entrypoint.sh neo4j
""", 0100555), "/startup/load-dump-and-start.sh")
.withCommand("/startup/load-dump-and-start.sh")
.withLogConsumer(f -> System.out.print(f.getUtf8String()));
neo4j.start();
driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", neo4j.getAdminPassword()));
}
#Test
void dataShouldHaveBeenLoaded() {
try (var session = driver.session()) {
var numNodes = session.run("MATCH (n) RETURN count(n)").single().get(0).asLong();
Assertions.assertTrue(numNodes > 0);
}
}
#AfterAll
void stopNeo4j() {
neo4j.stop();
}
}
Edit:
If you are on a recent enterprise edition, Christophe suggested the following solution on Twitter, which I do personally think it's superior, as it is less hacky.
https://github.com/ikwattro/neo4j-5-testcontainers-restore-backup/blob/main/src/test/java/dev/ikwattro/Neo4j5RestoreBackupExampleTest.java
It makes use of seed URIs for databases. Copying or binding the resource in his example works the same as in mine.
If you're using Neo4j 5, I suggest you make backups instead of dumps. Using backups you can take advantage of the seedUri option when creating a database, meaning you can create a database from an URI pointing to a backup on disk ( or in the neo4j container ). https://neo4j.com/docs/operations-manual/current/clustering/databases/#cluster-seed-uri
Here is an example using Testcontainers
package dev.ikwattro;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.assertj.core.api.Assertions.assertThat;
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#Testcontainers(disabledWithoutDocker = true)
public class Neo4j5RestoreBackupExampleTest {
#Container
private Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5.3.0-enterprise")
.withAdminPassword("password")
.withEnv("NEO4J_dbms_memory_heap_max__size", "256M")
.withEnv("NEO4J_dbms_databases_seed__from__uri__providers", "URLConnectionSeedProvider")
.withClasspathResourceMapping("backups", "/backups", BindMode.READ_ONLY)
.withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes");
#BeforeAll
void beforeAll() {
neo4j.start();
createDbFromBackup();
}
#Test
void testCreatingDbFromBackup() {
try (Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "password"))) {
try (Session session = driver.session(SessionConfig.forDatabase("worldcup22"))) {
var result = session.run("MATCH (n) RETURN count(n) AS c").single().get("c").asLong();
assertThat(result).isPositive();
}
}
}
private void createDbFromBackup() {
try (Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "password"))) {
try (Session session = driver.session(SessionConfig.forDatabase("system"))) {
session.run("""
CREATE DATABASE worldcup22 OPTIONS { existingData: "use", seedUri: "file:///backups/world-cup-2022-neo4j.backup"}
""");
}
}
}
}
You can find a working maven project here https://github.com/ikwattro/neo4j-5-testcontainers-restore-backup

JMeter / Beanshell “Error invoking bsh method: eval Sourced file:”

I am trying to call a method from java to connect to the mongoDB database, my machine can do it successfully but if I run it with a different one, I get this error.
2020-07-15 12:57:21,751 ERROR o.a.j.u.BeanShellInterpreter: Error invoking bsh method: eval Sourced file: inline evaluation of: ``import test.MongoDB; MongoDB.connect(vars.get("uri"));'' : Method Invocation MongoDB.connect
What could be the problem?
java
import java.util.LinkedHashMap;
import java.util.Map;
import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
public class MongoDB {
public static MongoDatabase database;
public static MongoClient mongoClients;
public static void connect(String uri) {
MongoClientURI uri_1 = new MongoClientURI(uri);
// Connecting With Server
mongoClients = new MongoClient(uri_1);
System.out.println("server connection successfully done");
database = mongoClients.getDatabase("Capacitacion");
System.out.println("Connect to database successfully");
System.out.println("DataBase Name: " + database.getName());
MongoCollection<Document> col_Capacitacion_Liceo = database.getCollection("Liceo");
} ```
jmeter
```import test.MongoDB;
MongoDB.connect(vars.get("uri"));;```
*
Beanshell is not Java and it doesn't support Diamond Operators
If for some reason you really need to use Beanshell - change this line:
MongoCollection<Document> col_Capacitacion_Liceo = database.getCollection("Liceo");
to this one:
MongoCollection col_Capacitacion_Liceo = database.getCollection("Liceo");
But be aware that starting from JMeter 3.1 users are encouraged to use JSR223 Test Elements and Groovy language for scripting.
You may also find MongoDB Performance Testing with JMeter article useful

How to connect to MongoDB in Java without specifying database name in the URL?

I am using the following mongodb driver.
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.2</version>
</dependency>
Here's how I connect
String textUri = "mongodb://<username>:<password>#ds027155.mlab.com:27155/";
MongoClientURI uri = new MongoClientURI(textUri);
MongoClient m = new MongoClient(uri);
I get the error. However if I mention database name
String textUri = "mongodb://<username>:<password>#ds027155.mlab.com:27155/<db-name>";
It works without any issue.. Acutally I want to list all the databases present on the server.
How do I do I mention uri without specifying the database name?
Also how do I list only user defined collections present in the DB.
MongoDatabase db = m.getDatabase("standupmeetingnotes");
ListCollectionsIterable<Document> listColl = db.listCollections();
MongoIterable<String> colls = db.listCollectionNames();
for (String s : colls) {
System.out.println(s);
}
It prints objectlabs-system,
objectlabs-system.admin.collections,
system.indexes also which are system defined collections apart from user defined ones.
Any way I will be able to omit those?
Thanks.
Answering the question in the topic: "How to get connect to MongoDB in Java without specifying it database name in the URL?". I've created simple class to connect to the MongoDB using API 3.2.2. and read list of the databases.
Apparently, there are two ways to connect to the MongoDB instance -- with URL and without URL. In previous versions there was way to connect to the DB (within instance) with username and password without URL either, but afaik, in 3.2.2 it is no longer possible. (I should admit, the pace at which MongoDB team changes their Java API is truly remarkable.)
Anyways, the class works equally with and without username/password (provided the access to the Mongo w/o password is possible at all). And the DB connect step can be executed at the later time, after connection established.
package testmongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import java.util.LinkedList;
import java.util.List;
public class MongoConnector {
private final MongoClient mongoClient;
private MongoDatabase db;
public MongoConnector(String host, int port)
{
this.mongoClient = new MongoClient(host, port);
}
public MongoConnector(String host, int port, String username, String password)
{
String textUri = "mongodb://"+username+":"+password+"#"+host+":"+port;
MongoClientURI uri = new MongoClientURI(textUri);
this.mongoClient = new MongoClient(uri);
}
public boolean connectToDB(String dbName)
{
this.db = mongoClient.getDatabase(dbName);
return this.db != null;
}
public List<String> listAllDB()
{
List<String> ret = new LinkedList<>();
MongoIterable<String> x = mongoClient.listDatabaseNames();
for(String t : x)
{
ret.add(t.toString());
}
return ret;
}
}

Bson cannot be resolved with Mongo DB /Java

I am getting this error on the last line in code below:
The type org.bson.conversions.Bson cannot be resolved. It is indirectly referenced from required .class files, I am using Mongo JavaDriver 3.0.2
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.util.JSON;
public class InsertDriver {
public static void main(String[] args)
{
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("postsdb");
DBCollection collection = db.getCollection("posts");
BasicDBObject doc1 = new BasicDBObject();
doc1.put("user", "Mike");
doc1.put("sports", "soccer");
doc1.put("tweet", "Hi..");
//String json = JSON.serialize( doc1);
//BasicDBObject bson = (BasicDBObject) JSON.parse( json );
List<BasicDBObject> docs = new ArrayList<BasicDBObject>();
docs.add(doc1);
collection.insert(docs); //ERROR HERE
}
}
Had the same issue. I've solved it by downloading the bson jar and adding it to the search path.
The Mongodb documentation states the following:
You can also download the jars directly from sonatype. Note:
mongodb-driver requires the following dependencies: bson and
mongodb-driver-core

How to declare second database for testing in Play Framework?

I want to run unit tests on a database other than the default one. Here is my application.conf:
application.secret="[cut]"
application.langs="en"
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost:3306/city_game?characterEncoding=UTF-8"
db.default.user=root
db.default.password=""
db.test.driver=com.mysql.jdbc.Driver
db.test.url="jdbc:mysql://localhost:3306/play_test?characterEncoding=UTF-8"
db.test.user=root
db.test.password=""
ebean.default="models.*"
ebean.test="models.*"
logger.root=ERROR
logger.play=INFO
logger.application=DEBUG
BaseModelTest.java:
package models;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.ddl.DdlGenerator;
import com.avaje.ebean.config.dbplatform.MySqlPlatform;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import play.test.FakeApplication;
import play.test.Helpers;
import java.io.IOException;
public class BaseModelTest
{
public static FakeApplication app;
public static DdlGenerator ddl;
#BeforeClass
public static void startApp() throws IOException
{
app = Helpers.fakeApplication();
Helpers.start(app);
String serverName = "test";
EbeanServer server = Ebean.getServer(serverName);
ServerConfig config = new ServerConfig();
ddl = new DdlGenerator();
ddl.setup((SpiEbeanServer) server, new MySqlPlatform(), config);
}
#AfterClass
public static void stopApp()
{
Helpers.stop(app);
}
#Before
public void dropCreateDb() throws IOException
{
// Drop
ddl.runScript(false, ddl.generateDropDdl());
// Create
ddl.runScript(false, ddl.generateCreateDdl());
}
}
However, I get results saved in the default database, and the test one has its tables created but empty. What I expect is to have the results written to the test db and default one untouched.
I somehow ended with different approach.
I still created separate real test database instance (because of stored procedures), but instead I used the Play1-like approach.
I have separates configuration sides beneath my main configuration (e.g. test configuration, prod specific stuff, stage specific stuff etc ..)
I load it via Global.scala as shown below (please note the exaple provided below works in in Play for java developers version as well)
object Global extends GlobalSettings {
override def onLoadConfig(config: Configuration, path: File, cl: ClassLoader, mode: Mode.Mode): Configuration = {
val modeFile: String = s"application.${mode.toString.toLowerCase}.conf"
Logger.error(s"Loading {${path.toURI}conf/application.conf}")
Logger.error(s"Appending mode specific configuration {${path.toURI}conf/$modeFile}")
val modeConfig = config ++ Configuration(ConfigFactory.load(modeFile))
super.onLoadConfig(modeConfig, path, cl, mode)
}
}
And the application.test.conf config file is as follows:
# test database
db.default.logStatements=false
db.default.jndiName=DefaultDS
db.default.url="jdbc:postgresql://127.0.0.1:5432/db-test"
db.default.user=user
db.default.password="password!##$"
db.default.driver=org.postgresql.Driver
This way I get following benefits:
I still write my tests the usual way
Play evolutions gets tested on CI / jenkins as well
I have to write my tests in the way I could safely retun them on the existing db instance w/ minimal assumptions about data and userbase. That way I'm 90% certain I will be able to run those against staging / prod environment with much less friction. (Controversial point)
I think you should separate your code
as these
#BeforeClass
public static void startApp() throws IOException {
app = Helpers.fakeApplication();
Helpers.start(app);
}
#Before
public void dropCreateDb() throws IOException {
String serverName = "test";
EbeanServer server = Ebean.getServer(serverName);
ServerConfig config = new ServerConfig();
DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);
// Drop
ddl.runScript(false, ddl.generateDropDdl());
// Create
ddl.runScript(false, ddl.generateCreateDdl());
}

Categories

Resources