Strongloop Oracle connecting via script - node.js

I'm currently testing Loopback and using the Arc interface.
I can connect to my oracle database and create models from the tables all served up in explorer. (all good).
but now I seem to be struggling when wanting to write some custom code and call an oracle procedure. I am unable to connect due to the oracle module not being found. (Arc works and I have all the correct packages installed)
I'm trying to connect to oracle for custom route but keep getting 'Cannot find module 'oracle''.
Code Example to try and connect is as follows;
module.exports = function(app) {
app.get('/oracletest', function(req, res) {
var settings = {};
var oracle = require("oracle")(settings);
var connectData = { "user": "userhere", "password": "passwordhere", "tns": "tnshere" };
oracle.connect(connectData, function(err, connection) {
console.log('must have connected woooohoooo');
connection.close(); // call this when you are done with the connection
});
}
This is following the guide from strong-oracle which is a dependancy installed with the loopback-oracle-connector.
Cheers

Thank you for catching the typo. The module name should be strong-oracle. Please use:
var oracle = require("strong-oracle")(settings);
I just fixed the README at https://github.com/strongloop/strong-oracle.

Related

DPI-1047: Cannot locate a 64-bit Oracle Client library from nodejs code

I'm trying to establish a simple database connection to run a sql query from an express/node app and when I hit my endpoint, I see the following error:
message:"DPI-1047: Cannot locate a 64-bit Oracle Client library: "The specified module could not be found". See https://oracle.github.io/odpi/doc/installation.html#windows for help\nNode-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html\nYou must have 64-bit Oracle client libraries in your PATH environment variable.\nIf you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from\nhttp://www.oracle.com/technetwork/topics/winx64soft-089540.html\nA Microsoft Visual Studio Redistributable suitable for your Oracle client library version must be available.
All i'm doing from my code is
result = connection.execute(sql);
I created a small little express application and I am trying to invoke a url on http://localhost:3000/url which does a simple select * from table query. I am not sure why I would need any kind of Oracle installation. Here is my full code:
var express = require("express");
var expressapp = express();
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
expressapp.listen(3000, () => {
console.log("Server running on port 3000");
});
expressapp.get("/url", (req, res, next) => {
let connection, result, sql;
sql = `SELECT * FROM user_table WHERE FNAME = 'TEST'`;
binds = {};
// For a complete list of options see the documentation.
options = {
outFormat: oracledb.OUT_FORMAT_OBJECT // query result format
// extendedMetaData: true, // get extra metadata
// fetchArraySize: 100 // internal buffer allocation size for tuning
};
connection = oracledb.getConnection({
user : "xxxxx",
password : "xxxxx",
connectString : "xxxxxxxxxxxxxxx"
});
result = connection.execute(sql);
console.log("Response: ");
console.log(result);
res.json(result);
});
The oracle 'oracledb' driver (node-oracledb) requires the Oracle client to connect to the database.
You can find the Oracle client at https://www.oracle.com/database/technologies/instant-client.html
The solution is:
oracledb.initOracleClient({libDir: 'D:\\Oracle\\instantclient_19_17'});
Here the path(D:\Oracle\instantclient_19_17) we have mentioned is pointing to folder containing Oracle Instant Client's content.
Oracle Instant Client Download (is dependent on OS & 32 OR 64-bit System etc) which one is suitable.
Ex: https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html
We downloaded just the Basic Package from this link for our Windows 64-bit System.
After download please make sure that download should have these files else this issue will not resolve and we will simply try many things instead of fixing the actual issue.
Once you have this download in place then just pointing to it using the above mentioned code will resolve the issue.
You can refer the following links for more detials:
https://node-oracledb.readthedocs.io/en/latest/user_guide/initialization.html#oracleclientloadingwindows
https://node-oracledb.readthedocs.io/en/latest/user_guide/introduction.html#getstarted

Is it possible to browserify the "tedious" module so that the nodejs program can be run in the browser?

I'm a beginner to Node.js and I'm currently building a Node.js program that accesses and queries a Microsoft Azure SQL database with the "tedious" module (see code below) and puts the data onto a html webpage. I want to run this code in a browser so I used browserify to bundle the modules together. However, when this code is run in Google Chrome, the following error is returned: require is not defined. Is there a fix? Is it even possible to use the tedious module in Chrome? If it isn't possible, do I need to use an intermediate server between the Node.js application and the webpage?
var Connection = require('tedious').Connection;
var config = {
userName: 'hackmatch',
password: 'hackvalley123!',
server: 'hackmatch.database.windows.net',
options: {encrypt: true, database: 'AdventureWorks'}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
// If no error, then good to proceed.
console.log("Connected");
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
Thanks in advance for your help! :)
No. This module can only be used in Node.
tedious depends on the node.js net module to make a connection to the database server. This module has no equivalent on the browser, as web pages cannot make arbitrary network connections.
Even if it were possible to use this module in the browser, it'd be a terrible idea. You'd be allowing anyone on your web site to connect directly to your SQL server and run SQL queries. This can only end badly.

Bitnami Meanstack Mongoose Connection

I created a simple service in Ubuntu 16.04 with mongo db node and express to return data to an angular 2 app.
I have a file called server.js that connects to a local mongodb instance with a database called game and a collection called players. It works fine installed on my local machine. However I am trying to deploy it with Bitnami's mean stack image on amazon ec2. (bleh mouth full). I have set ports correctly according to this guide, and I can connect to it remotely. However, I can't get mongoose to connect to any database. here is my code that works on my local machine.
mongoose.connect('mongodb://localhost:27017/game');
router.route('/player')
.get(function(req, res) {
console.log(mongoose.connection.readyState);
Player.find({"player":user,"password":password},function(err, Test) {
if (err)
res.send(err);
res.json(Test);
});
});
And here is my adjusted code for the mean stack image
mongoose.connect('mongodb://root:"My-Root-Password#127.0.0.1:27017/game');
router.route('/player')
.get(function(req, res) {
console.log(mongoose.connection.readyState);
Player.find({"player":user,"password":password},function(err, Test) {
if (err)
res.send(err);
res.json(Test);
});
});
On my local machine I get a value of 1 on the console.log and value of zero on the mean stack image. I'm not sure how to connect to bitnami's mongo instance with mongoose. I have checked that game exist and has the data I want.
I found a fix Although I don't yet fully understand it. It came from the guide I posted here . First I had to un comment out the section of the mongodb.conf that says noauth = true then comment out the line that says auth = true. I then restart mongo, and create a new user with permissions to read and write the the data base I want to use like this
db.createUser({
user: "NEW USERNAME",
pwd: "NEW PASSWORD",
roles:[
{
"role" : "readWrite",
"db": "game"
}
]})
After creating the user I undo what I did to noauth = true and auth = true, and restart mongodb. Then I am able to connect with mongoose like this
mongoose.connect('mongodb://NEW USERNAME:NEW PASSWORD#127.0.0.1:27017/game');
With MongoDB 3.0, they added a new authentication mechanism for MongoDB (more details in the links below).
Authentication information: https://docs.mongodb.com/manual/core/authentication/
How to use the new authentication mechanism: https://www.mongodb.com/blog/post/improved-password-based-authentication-mongodb-30-scram-explained-part-2
Due to this, the guide provides that workaround to get the connection with the database. Now, you have created that user with "readWrite" privileges on your database so you are able to use it.

How to connect with node.js to mongoDB without running additional command windows

I've read this tutorial:
http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/
in part 3, the author explains how to connect to MongoDB, but his way requires running of separate command windows.
I want to know if there is a way to connect the DB i've created, from the application code, without running other command windows.
Thanks a lot.
The mongod command is used to start the Mongo server. To connect a db client to it from your application, you can take a look at this example from the official MongoDB documentation (scroll to "Connect to MongoDB"). You simply need to do something like
var MongoClient = require('mongodb').MongoClient;
// Connection URL
var url = 'mongodb://localhost:27017/nodetest1';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, db) {
console.log("Connected succesfully to server");
db.close();
});

Connection to Mongodb-Native-Driver in express.js

I am using mongodb-native-driver in express.js app. I have around 6 collections in the database, so I have created 6 js files with each having a collection as a javascript object (e.g function collection(){}) and the prototypes functions handling all the manipulation on those collections. I thought this would be a good architecture.
But the problem I am having is how to connect to the database? Should I create a connection in each of this files and use them? I think that would be an overkill as the connect in mongodb-native-driver creates a pool of connections and having several of them would not be justified.
So how do I create a single connection pool and use it in all the collections.js files? I want to have the connection like its implemented in mongoose. Let me know if any of my thought process in architecture of the app is wrong.
Using Mongoose would solve these problems, but I have read in several places thats it slower than native-driver and also I would prefer a schema-less models.
Edit: I created a module out of models. Each collection was in a file and it took the database as an argument. Now in the index.js file I called the database connection and kept a variable db after I got the database from the connection. (I used the auto-reconnect feature to make sure that the connection wasn't lost). In the same index.js file I exported each of the collections like this
exports.model1 = require('./model1').(db)
exprorts.model2 = require('./model2').(db)
This ensured that the database part was handled in just one module and the app would just call function that each model.js file exported like save(), fincdbyid() etc (whatever you do in the function is upto you to implement).
how to connect to the database?
In order to connect using the MongoDB native driver you need to do something like the following:
var util = require('util');
var mongodb = require('mongodb');
var client = mongodb.MongoClient;
var auth = {
user: 'username',
pass: 'password',
host: 'hostname',
port: 1337,
name: 'databaseName'
};
var uri = util.format('mongodb://%s:%s#%s:%d/%s',
auth.user, auth.pass, auth.host, auth.port, auth.name);
/** Connect to the Mongo database at the URI using the client */
client.connect(uri, { auto_reconnect: true }, function (err, database) {
if (err) throw err;
else if (!database) console.log('Unknown error connecting to database');
else {
console.log('Connected to MongoDB database server at:');
console.log('\n\t%s\n', uri);
// Create or access collections, etc here using the database object
}
});
A basic connection is setup like this. This is all I can give you going on just the basic description of what you want. Post up some code you've got so far to get more specific help.
Should I create a connection in each of this files and use them?
No.
So how do I create a single connection pool and use it in all the collections.js files?
You can create a single file with code like the above, lets call it dbmanager.js connecting to the database. Export functions like createUser, deleteUser, etc. which operate on your database, then export functionality like so:
module.exports = {
createUser: function () { ; },
deleteUser: function () { ; }
};
which you could then require from another file like so:
var dbman = require('./dbmanager');
dbman.createUser(userData); // using connection established in `dbmanager.js`
EDIT: Because we're dealing with JavaScript and a single thread, the native driver indeed automatically handles connection pooling for you. You can look for this in the StackOverflow links below for more confirmation of this. The OP does state this in the question as well. This means that client.connect should be called only once by an instance of your server. After the database object is successfully retrieved from a call to client.connect, that database object should be reused throughout the entire instance of your app. This is easily accomplished by using the module pattern that Node.JS provides.
My suggestion is to create a module or set of modules which serves as a single point of contact for interacting with the database. In my apps I usually have a single module which depends on the native driver, calling require('mongodb'). All other modules in my app will not directly access the database, but instead all manipulations must be coordinated by this database module.
This encapsulates all of the code dealing with the native driver into a single module or set of modules. The OP seems to think there is a problem with the simple code example I've posted, describing a problem with a "single large closure" in my example. This is all pretty basic stuff, so I'm adding clarification as to the basic architecture at work here, but I still do not feel the need to change any code.
The OP also seems to think that multiple connections could possibly be made here. This is not possible with this setup. If you created a module like I suggest above then the first time require('./dbmanager') is called it will execute the code in the file dbmanager.js and return the module.exports object. The exports object is cached and is also returned on each subsequent call to require('./dbmanager'), however, the code in dbmanager.js will only be executed the first require.
If you don't want to create a module like this then the other option would be to export only the database passed to the callback for client.connect and use it directly in different places throughout your app. I recommend against this however, regardless of the OPs concerns.
Similar, possibly duplicate Stackoverflow questions, among others:
How to manage mongodb connections in nodejs webapp
Node.JS and MongoDB, reusing the DB object
Node.JS - What is the right way to deal with MongoDB connections
As accepted answer says - you should create only one connection for all incoming requests and reuse it, but answer is missing solution, that will create and cache connection. I wrote express middleware to achieve this - express-mongo-db. At first sight this task is trivial, and most people use this kind of code:
var db;
function createConnection(req, res, next) {
if (db) { req.db = db; next(); }
client.connect(uri, { auto_reconnect: true }, function (err, database) {
req.db = db = databse;
next();
});
}
app.use(createConnection);
But this code lead you to connection-leak, when multiple request arrives at the same time, and db is undefined. express-mongo-db solving this by holding incoming clients and calling connect only once, when module is required (not when first request arrives).
Hope you find it useful.
I just thought I would add in my own method of MongoDB connection for others interested or having problems with different methods
This method assumes you don't need authentication(I use this on localhost)
Authentication is still easy to implement
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
var client = new MongoClient(new Server('localhost',27017,{
socketOptions: {connectTimeoutMS: 500},
poolSize:5,
auto_reconnect:true
}, {
numberOfRetries:3,
retryMilliseconds: 500
}));
client.open(function(err, client) {
if(err) {
console.log("Connection Failed Via Client Object.");
} else {
var db = client.db("theDbName");
if(db) {
console.log("Connected Via Client Object . . .");
db.logout(function(err,result) {
if(!err) {
console.log("Logged out successfully");
}
client.close();
console.log("Connection closed");
});
}
}
});
Credit goes to Brad Davley which goes over this method in his book (page 231-232)

Resources