how to check from a driver, if mongoDB server is running - java

I wonder, if there is a way to check if mongoDB server is running from java driver for mongoDB?
According to the tutorial, I can do
Mongo m = new Mongo();
// or
Mongo m = new Mongo( "localhost" , 27017 );
// and
DB db = m.getDB( "mydb" );
But how to check that I can use these Mongo and DB? I see no isConnected() method in the API.
db.getConnector().isOpen()
returns true
The only way I found is call db.getDatabaseNames() and catch MongoException.
If there some more civilized approach?

You can run a ping command
Mongo mongo = new Mongo();
DBObject ping = new BasicDBObject("ping", "1");
try {
mongo.getDB("dbname").command(ping);
} catch (MongoException e) {
...
}

I've found this to be more direct than the ping command:
Mongo mongo = new Mongo();
try {
mongo.getConnector().getDBPortPool(mongo.getAddress()).get().ensureOpen();
} catch (Exception e) {
...
}

if there is a way to check if mongoDB server is running from java driver for MongoDB?
So if you can do the following:
Mongo m = new Mongo( "localhost" , 27017 );
DB db = m.getDB( "mydb" );
Then you are connected to the database, otherwise that m.getDB() would be throwing an exception. If you can connect to the database, then the MongoDB server is running.
The only way I found is call db.getDatabaseNames() and catch MongoException.
If there some more civilized approach?
Is there something specifically wrong with this approach?
The driver basically runs in a sandbox where it can or cannot connect. You're asking the driver to know something specific about the server (is process X running?), but that's not the driver's job. It can either connect or it can't, it's not responsible for operating the service/process, just for connecting to it.
To know that the process is actually running, you need administrative functions on that server that allow you to check that mongod is indeed running with the correct parameters.

public boolean keepAlive(Mongo mongo) {
return mongo.getAddress() != null;
}
This will return null for address if mongo is down. You can look within the implementation of getAddress() to see why it is a good way to check the mongo's status.
I assume you've initialized the mongo parameter properly.

I haven't tested this thoroughly (only using a localhost mongo) but it appears to work so far:
public boolean mongoRunningAt(String uri) {
try {
Mongo mongo = new Mongo(new MongoURI(uri));
try {
Socket socket = mongo.getMongoOptions().socketFactory.createSocket();
socket.connect(mongo.getAddress().getSocketAddress());
socket.close();
} catch (IOException ex) {
return false;
}
mongo.close();
return true;
} catch (UnknownHostException e) {
return false;
}
}
And the tests I've used:
#Test
public void whenMongoNotAvailableAtSpecificURLThenTheLoaderKnows() {
assertThat(mongoRunningAt("mongodb://127.0.0.1:12345"), is(false));
}
#Test
public void whenMongoAvailableAtSpecificURLThenTheLoaderKnows() {
assertThat(mongoRunningAt("mongodb://127.0.0.1:27017"), is(true));
}
It's not exactly using a well defined public API so use at your own risk.

Related

How to get number of used/opened connections in a MQ Connection factory configured in WebSphere Application Server

I have a java application running on WebSphere 8.5.5.12 server. I connect to other applications via MQ. I have faced a performance issue with the application and found that whenever the MQ reply is getting timeout, the Queue connection was not closed properly. I have fixed the issue. I am planning to increase the Maximum connection for the particular Queue Connection factory and i want to get the number of connection used/opened in the Queue Connection Factory via code, so that i can increase the maximum connections accordingly based on the traffic/volume. Any leads would be much helpful.
To learn the number of connections used and the number of queues opened by an application, you can use the MQSC DISPLAY CONN command like this:-
DISPLAY CONN(*) TYPE(ALL) ALL WHERE(OBJNAME EQ reply-q-name)
This will show you all the connections and all the open handles.
You can also discover exactly the same data using a programatic interface called PCF commands, although given how many excellent MQ admin tools there are out there, I'm not sure why you would need to do this "via code" as you put it?
For your second part of your question, how do you change the maximum connections based on load.
I have a some sample code using a datasource that may help to answer you question. Where I using name=built-in-derby-datasource, you can change the name to your Queue Connection factory name. If you need the lookup, change this jndi name jdbc/built-in-derby-datasource to your Queue Connection factory jndi name.
The code will get the admin client giving you access to queryMBeans. After you have the mbean, you can change maximum connections dynamically while the server is running.
#SuppressWarnings("unchecked")
public void AdminClientExample()
{
Object adminClient = null;
// Need to set the properties, type, host and port, defaults likely will work for most
Properties acProps = new Properties();
acProps.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
acProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
acProps.setProperty(AdminClient.CONNECTOR_PORT, "8880");
// Set if security is enabled
//acProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");
//acProps.setProperty(AdminClient.USERNAME, "userid");
//acProps.setProperty(AdminClient.PASSWORD, "userid password");
try
{
adminClient = AdminClientFactory.createAdminClient(acProps);
}
catch (Exception e)
{
e.printStackTrace();
}
ObjectInstance obi = null;
ObjectName obn = null;
Set<ObjectInstance> s = null;
try {
// The two types to use are J2CConnectionFactory and DataSource if searching through a list of mbeans of that type.
// type=J2CConnectionFactory
// type=DataSource
// obn = new ObjectName("WebSphere:type=DataSource,*");
// s1 =((AdminClient)adminClient).queryMBeans(obn, null); // search through s1
// You can provide the name like this,
obn = new ObjectName("WebSphere:name=built-in-derby-datasource,*");
s =((AdminClient)adminClient).queryMBeans(obn, null);
// s should contain WebSphere:name=built-in-derby-datasource,process=server1,platform=dynamicproxy,node=DefaultNode01,JDBCProvider=Derby JDBC Provider (XA),diagnosticProvider=true,j2eeType=JDBCDataSource,J2EEServer=server1,Server=server1,version=9.0.0.11,type=DataSource,mbeanIdentifier=cells/DefaultCell01/resources.xml#DataSource_9007001,JDBCResource=Derby JDBC Provider (XA),cell=DefaultCell01,spec=1.0
} catch (Exception e) {
e.printStackTrace();
}
if (s == null) {
System.out.println("Did not find MBeans querying for object name " + obn.toString());
return;
} else {
obi = s.iterator().next();
}
// Normally the application using the connection pool will have
// already done the lookup which creates the objects
// required to change maxConnections. This lookup is only for
// this example.
InitialContext ctx;
try {
ctx = new InitialContext();
ctx.lookup("jdbc/built-in-derby-datasource");
} catch (Exception e) {
e.printStackTrace();
}
// show the connection pool contents
Object [] parms = null;
String [] parmsTypes = null;
try {
String ss = (String) ((AdminClient)adminClient).invoke(obi.getObjectName(), "showPoolContents", parms, parmsTypes);
System.out.println(ss);
} catch (Exception e) {
e.printStackTrace();
}
// get maxConnections
try {
Object maxConnections = ((AdminClient)adminClient).getAttribute(obi.getObjectName(), "maxConnections");
System.out.println(maxConnections);
} catch (Exception e) {
e.printStackTrace();
}
// change the maxConnections to 11,
try {
Integer it = new Integer(11);
Attribute at = new Attribute("maxConnections", it);
((AdminClient)adminClient).setAttribute(obi.getObjectName(), at );
} catch (Exception e) {
e.printStackTrace();
}
// show the connection pool contents, maxConnection now should be 11.
// or you can use the get maxConnection to check
// the changed value.
try {
String ss = (String) ((AdminClient)adminClient).invoke(obi.getObjectName(), "showPoolContents", parms, parmsTypes);
System.out.println(ss);
// or
Object maxConnections = ((AdminClient)adminClient).getAttribute(obi.getObjectName(), "maxConnections");
System.out.println(maxConnections);
} catch (Exception e) {
e.printStackTrace();
}
}

make mongoClient object/any object available across the application

Hello i am working with mongodb java driver. In their documentation, they mentioned that,
The MongoClient class is designed to be thread safe and shared among threads.
Typically you create only 1 instance for a given database cluster and use it across
your application.
So, I want to make this object available for every user. how can i do this?
The best way to do this is to use Singleton design pattern. This is the code-
public class MongoDBManager {
public MongoClient mongoClient = null;
String host = "127.0.0.1";
static MongoDBManager mongo=new MongoDBManager();
private MongoDBManager() {
try {
mongoClient = new MongoClient( host , 27017);
} catch (UnknownHostException e) {
System.err.println("Connection errors");
e.printStackTrace();
}
}
public static MongoDBManager getInstance(){
return mongo;
}
}
Call only MongoDBManager.getInstance() whenever you need connection. only one object will be used.

Openshift can't connect to mongoDB from java code, time out

I've got a MongoDB cartridge installed on openshift and i'm having troubles with connecting to it from java code. Ip address, port and credentials are taken from openshift's RockMongo cartridge. The following method invocation:
public Document insert(String audio, String username) {
Document document = new Document();
document.put("username", username);
document.put("audio", audio);
document.put("timestamp", new Date());
collection.insertOne(document);
return document;
}
and this mongo client configuration:
private static MongoClient build() throws UnknownHostException {
if (mongoClient == null) {
mongoClient = new MongoClient(
new MongoClientURI( "mongodb://admin:password#X.X.X.X:27017/dbName"));
}
return mongoClient;
}
public static MongoCollection<Document> getCollection(String collectionName) {
try {
build();
} catch (UnknownHostException e) {
}
MongoDatabase db = mongoClient.getDatabase(dbName);
MongoCollection<Document> collection = db.getCollection(collectionName);
return collection;
}
results in INFO: No server chosen by PrimaryServerSelector from cluster description ClusterDescription, and exception: Timed out after 30000 ms while waiting for a server that matches PrimaryServerSelector.
EDIT: I can't connect with mongoDB service on openshift via mongo terminal application either: "exception: connect failed", so I think it's openshift configuration issue. Port forwarding and the service itself are started
I suppose you have not correctly configure cluster (message in logs told about this problem), I'm not sure how OpenShift Cratridge works, but I recommend you to check if it has mondo-db correctly started. Check it via ssh client and run mongo-db command to check its status and if started. Take a look on this question: Java MongoClient cannot connect to primary, I suppose it give you some idea how to check where you have problem.

cassandra single node connection error

i am trying to use cassandra as database for an app i am working on. The app is a Netbeans platform app.
In order to start the cassandra server on my localhost i issue Runtime.getRuntime().exec(command)
where command is the string to start the cassandra server and then i connect to the cassandra sever with the datastax driver. However i get the error:
com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: /127.0.0.1:9042 (com.datastax.driver.core.TransportException: [/127.0.0.1:9042] Cannot connect))
at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:199)
at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:80)
at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1154)
at com.datastax.driver.core.Cluster.getMetadata(Cluster.java:318)
at org.dhviz.boot.DatabaseClient.connect(DatabaseClient.java:43)
at org.dhviz.boot.Installer.restored(Installer.java:67)
....
i figure it out that the server requires some time to start so i have added the line Thread.sleep(MAX_DELAY_SERVER) which seem to resolve the problem.
Is there any more elegant way to sort this issue?
Thanks.
Code is below.
public class Installer extends ModuleInstall {
private final int MAX_DELAY_SERVER = 12000;
//private static final String pathSrc = "/org/dhviz/resources";
#Override
public void restored() {
/*
-*-*-*-*-*DESCRIPTION*-*-*-*-*-*
IMPLEMENT THE CASSANDRA DATABASE
*********************************
*/
DatabaseClient d = new DatabaseClient();
// launch an instance of the cassandra server
d.loadDatabaseServer();
/*wait for MAX_DELAY_SERVER milliseconds before launching the other instructions.
*/
try {
Thread.sleep(MAX_DELAY_SERVER);
Logger.getLogger(Installer.class.getName()).log(Level.INFO, "wait for MAX_DELAY_SERVER milliseconds before the connect database");
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
Logger.getLogger(Installer.class.getName()).log(Level.INFO, "exeption in thread sleep");
}
d.connect("127.0.0.1");
}
}
public class DatabaseClient {
private Cluster cluster;
private Session session;
private ShellCommand shellCommand;
private final String defaultKeyspace = "dhviz";
final private String LOAD_CASSANDRA = "launchctl load /usr/local/Cellar/cassandra/2.1.2/homebrew.mxcl.cassandra.plist";
final private String UNLOAD_CASSANDRA = "launchctl unload /usr/local/Cellar/cassandra/2.1.2/homebrew.mxcl.cassandra.plist";
public DatabaseClient() {
shellCommand = new ShellCommand();
}
public void connect(String node) {
//this connect to the cassandra database
cluster = Cluster.builder()
.addContactPoint(node).build();
// cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(12000);
Metadata metadata = cluster.getMetadata();
System.out.printf("Connected to cluster: %s\n",
metadata.getClusterName());
for (Host host
: metadata.getAllHosts()) {
System.out.printf("Datatacenter: %s; Host: %s; Rack: %s\n",
host.getDatacenter(), host.getAddress(), host.getRack());
}
session = cluster.connect();
Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "connected to server");
}
public void loadDatabaseServer() {
if (shellCommand == null) {
shellCommand = new ShellCommand();
}
shellCommand.executeCommand(LOAD_CASSANDRA);
Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "database cassandra loaded");
}
public void unloadDatabaseServer() {
if (shellCommand == null) {
shellCommand = new ShellCommand();
}
shellCommand.executeCommand(UNLOAD_CASSANDRA);
Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "database cassandra unloaded");
}
}
If you are calling cassandra without any parameters in Runtime.getRuntime().exec(command) it's likely that this is spawning cassandra as a background process and returning before the cassandra node has fully started and is listening.
I'm not sure why you are attempting to embed cassandra in your app, but you may find using cassandra-unit useful for providing a mechanism to embed cassandra in your app. It's primarily used for running tests that require a cassandra instance, but it may also meet your use case.
The wiki provides a helpful example on how to start an embedded cassandra instance using cassandra-unit:
EmbeddedCassandraServerHelper.startEmbeddedCassandra();
In my experience cassandra-unit will wait until the server is up and listening before returning. You could also write a method that waits until a socket is in use, using logic opposite of this answer.
I have changed the code to the following taking inspiration from the answers below. Thanks for your help!
cluster = Cluster.builder()
.addContactPoint(node).build();
cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(50000);
boolean serverConnected = false;
while (serverConnected == false) {
try {
try {
Thread.sleep(MAX_DELAY_SERVER);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
}
cluster = Cluster.builder()
.addContactPoint(node).build();
cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(50000);
session = cluster.connect();
serverConnected = true;
} catch (NoHostAvailableException ex) {
Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "trying connection to cassandra server...");
serverConnected = false;
}
}

How to check if a Mongo repository is up and running [duplicate]

I wonder, if there is a way to check if mongoDB server is running from java driver for mongoDB?
According to the tutorial, I can do
Mongo m = new Mongo();
// or
Mongo m = new Mongo( "localhost" , 27017 );
// and
DB db = m.getDB( "mydb" );
But how to check that I can use these Mongo and DB? I see no isConnected() method in the API.
db.getConnector().isOpen()
returns true
The only way I found is call db.getDatabaseNames() and catch MongoException.
If there some more civilized approach?
You can run a ping command
Mongo mongo = new Mongo();
DBObject ping = new BasicDBObject("ping", "1");
try {
mongo.getDB("dbname").command(ping);
} catch (MongoException e) {
...
}
I've found this to be more direct than the ping command:
Mongo mongo = new Mongo();
try {
mongo.getConnector().getDBPortPool(mongo.getAddress()).get().ensureOpen();
} catch (Exception e) {
...
}
if there is a way to check if mongoDB server is running from java driver for MongoDB?
So if you can do the following:
Mongo m = new Mongo( "localhost" , 27017 );
DB db = m.getDB( "mydb" );
Then you are connected to the database, otherwise that m.getDB() would be throwing an exception. If you can connect to the database, then the MongoDB server is running.
The only way I found is call db.getDatabaseNames() and catch MongoException.
If there some more civilized approach?
Is there something specifically wrong with this approach?
The driver basically runs in a sandbox where it can or cannot connect. You're asking the driver to know something specific about the server (is process X running?), but that's not the driver's job. It can either connect or it can't, it's not responsible for operating the service/process, just for connecting to it.
To know that the process is actually running, you need administrative functions on that server that allow you to check that mongod is indeed running with the correct parameters.
public boolean keepAlive(Mongo mongo) {
return mongo.getAddress() != null;
}
This will return null for address if mongo is down. You can look within the implementation of getAddress() to see why it is a good way to check the mongo's status.
I assume you've initialized the mongo parameter properly.
I haven't tested this thoroughly (only using a localhost mongo) but it appears to work so far:
public boolean mongoRunningAt(String uri) {
try {
Mongo mongo = new Mongo(new MongoURI(uri));
try {
Socket socket = mongo.getMongoOptions().socketFactory.createSocket();
socket.connect(mongo.getAddress().getSocketAddress());
socket.close();
} catch (IOException ex) {
return false;
}
mongo.close();
return true;
} catch (UnknownHostException e) {
return false;
}
}
And the tests I've used:
#Test
public void whenMongoNotAvailableAtSpecificURLThenTheLoaderKnows() {
assertThat(mongoRunningAt("mongodb://127.0.0.1:12345"), is(false));
}
#Test
public void whenMongoAvailableAtSpecificURLThenTheLoaderKnows() {
assertThat(mongoRunningAt("mongodb://127.0.0.1:27017"), is(true));
}
It's not exactly using a well defined public API so use at your own risk.

Categories

Resources