Setting up MongoLab or MongoHQ with Play Framework on Heroku - mongodb

I can't seem to find any instructions for setting up either MongoHQ or MongoLab with Play Framework on Heroku.
Is there something similar to this which is for the Spring Framework (I believe) https://devcenter.heroku.com/articles/mongohq#use-with-java that I can follow?
Or does anyone have any instructions that they can provide.

MongoHQ adds a MONGOHQ_URL to your Heroku config environment
heroku config
Which returns something like
MONGOHQ_URL: mongodb://heroku:1234#someserver.mongohq.com:10071/app1234
Use this envronment variable inside your application to fetch which URI to connect Mongo to. I have an overriden property that can be specified in the Procfile
web: target/start -Dhttp.port=$PORT -Dmongodb.uri=$MONGOHQ_URL
And in a Play model class I connect and query Mongo with:
val mongoUri = MongoUri(Play.configuration.getString("mongodb.uri").get)
val mongoCollection = mongoUri.connectDB match {
case Left(thrown) => throw thrown
case Right(database) => {
mongoUri.username.map { username =>
mongoUri.password.map { password =>
database.underlying.authenticate(username,password)
}
}
database.apply("mycollection")
}
}
def findSomething(something:String) = {
val searchTerm = MongoDBObject("something" -> something)
mongoCollection.findOne(searchTerm) map { mongoObject =>
Logger.info("Found %s".format(mongoObject.getAs[String]("somethingElse")))
}
}
Assumptions made: Play 2.0, Scala, Casbah

Here is an example app that uses MongoHQ, Play 2, Scala, and works on Heroku:
https://github.com/jamesward/play2bars/tree/scala-mongodb
There aren't really instructions, just some simple code.

Related

Aplakka scala s3 connector hangs when trying to put data

I'm trying to process aws s3 put into bucket, with a simple string, I couldn't do this with alpakka (scala) but I can process with same request using aws java sdk
Using alpakka my thread just hangs not processing anything, Future.onComplete not triggering
I've tried to specify aplakka conf file like this ('*' marks covers sensitive data) :
alpakka.s3 {
aws {
credentials {
provider = static
access-key-id = "********"
secret-access-key = "********"
}
region {
provider = static
default-region = "*****"
}
}
}
I do have ~/.aws/credentials on my machine correct, I can connect both with aws sdk and aws cli
As I understand ideally I may not specify any apakka.s3 creds at all, like in aws java sdk
I've already checked this article https://discuss.lightbend.com/t/alpakka-s3-connection-issue/6551/2 nothing worked
My example is strainghforward scala code from docs:
val file: Source[ByteString, NotUsed] =
Source.single(ByteString(body))
val s3Sink: Sink[ByteString, Future[MultipartUploadResult]] =
S3.multipartUpload(bucket, bucketKey)
val result: Future[MultipartUploadResult] =
file.runWith(s3Sink)
but actually I also need my source to be InputStream
val source: Source[ByteString, Future[IOResult]] = StreamConverters.fromInputStream(() => is, 4096)
PS: I don't actually get why i need to specify some host like this:
endpoint-url = "http://localhost:9000"
If you leave alpakka.s3.aws empty, it will use the default AWS configuration methods, as in the CLI (e.g. you can use the AWS_REGION environment variable to set the region and the standard AWS credential file). You can also leave alpakka.s3.aws.credentials empty to use the default AWS credential methods and set the AWS region via
alpakka.s3 {
aws {
region {
provider = static
default-region = "us-east-1"
}
}
}
endpoint-url is only for use with alternative (non-AWS) implementations of the S3 API (e.g. minio). If you're setting it, you will not be able to connect to AWS S3.

Having Trouble Initializing Postgresql Database Through PG-Promise

I'm completely new to Express/Postgresql and I'm trying to learn them to create a web application. After some poking around, I decided that I wanted to develop my back-end with TypeScript. I successfully converted all my other files from JavaScript to TypeScript, but I still can't figure out how to initialize the pg-promise connection in TypeScript!
I've been trying to follow the TypeScript guidelines in this link here. https://github.com/vitaly-t/pg-promise/tree/master/typescript
// Initialize the PostGres database conneciton for use throughout
the entire application
import {IMain, IDatabase} from 'pg-promise';
import * as pgPromise from 'pg-promise';
const pgp: IMain = pgPromise({
query(e: any) {
console.log('QUERY RESULT:', e.query);
},
receive(data: any, result: any, e: any) {
console.log(`DATA FROM QUERY ${e.query} WAS RECEIVED.`);
}
});
const connection: any = {
host: 'localhost',
port: 5432,
database: 'RushHub',
user: 'RyanArifin',
password: null
}
const db: IDatabase<any> = pgp(connection);
export {
db
};
I currently am getting the error "TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof pgPromise' has no compatible call signatures." This error is coming from when I try to set my initialization options. Any help would be appreciated, thanks!
This is standard TypeScript configuration flag - esModuleInterop. When set to true, the import syntax is import pgPromise from 'pg-promise';, and when false, which is the default, the syntax is import * as pgPromise from 'pg-promise';.
The library gives you example for the default TypeScript configuration.

Can`t connect my MySQL database in Vapor project

I'm new at Vapor and I wanted to try to connect my MySQL database. I found on official documentation how to do it but when I try to send a query it throws an error:
No services are available for 'DatabaseConnectionPoolCache'. (Container.swift:112)
I just copy-paste the code from documentation and it doesn`t work. Could someone help me to found out why?
I have MySQL#5.7 on Mojave. Actually simple requests work well, for example :
router.get("hey") { req in
return "Stas, hey"
}
Code in configure.swift :
import FluentSQLite
import MySQL
import Vapor
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
/// Register providers first
try services.register(FluentSQLiteProvider())
try services.register(MySQLProvider())
/// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
/// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
/// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
/// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
services.register(migrations)
//Configure a MySQL database
let mysql = try MySQLDatabase(config: MySQLDatabaseConfig(
hostname: "127.0.0.1",
port: 3306,
username: "root",
password: "7374",
database: "WORK_TIME"))
///Register to the congig
var mysqlDatabases = DatabasesConfig()
mysqlDatabases.add(database: mysql, as: .mysql)
services.register(mysqlDatabases)
}
My query in main.swift :
public struct MySQLVersion: Codable {
let version: String
}
router.get("sql") { req in
return req.withPooledConnection(to: .mysql) {conn in
return conn.raw("SELECT ##version as version")
.all(decoding: MySQLVersion.self)
}.map { rows in
return rows[0].version
}
}
It should return the version of my MySQL but it throws a strange error.
Your issue is that there is some leftover SQLite stuff from the original project template.
Start by removing the fluent-sqlite dependency from your Package.swift file and the FluentSQLite target from any target dependencies. Then run swift package update (and vapor xcode if you use Xcode) in your terminal.
Now that you have removed the FluentSQLite dependency from your project, you should be able to follow to compiler errors to fix your issue. Here are the ones I found:
import FluentSQLite
import MySQL
Should be:
import FluentMySQL
try services.register(FluentSQLiteProvider())
try services.register(MySQLProvider())
Should be
try services.register(FluentMySQLProvider())
Delete this, since you are using MySQL instead of SQLite:
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
migrations.add(model: Todo.self, database: .sqlite)
Should be
migrations.add(model: Todo.self, database: .mysql)
I think that covers everything. Your /sql route should work now.
To solve this problem you should get rid of all leftover SQLite stuff from the original project and have to write your routes in routes.swift

How do I log SQL statements in Vapor 3/Fluent?

It looks like in Vapor 2 you could do something like:
let query = <some fluent query object>
logger?.debug(query)
and it would print out the full SQL statement, but I'm not seeing any documentation of how to do that now in Vapor 3.
How can I see what SQL is being generated by my QueryBuilder?
Thanks to Nick in the comments, who pointed me to the right set of docs. This can be accomplished by using the enableLogging method. So now my configure.swift includes this code:
let dbConfig: PostgreSQLDatabaseConfig
if let url = Environment.get("DATABASE_URL"), let psqlConfig = PostgreSQLDatabaseConfig(url: url, transport: .unverifiedTLS) {
dbConfig = psqlConfig
} else {
dbConfig = ...something for the local db...
}
let postgresql = PostgreSQLDatabase(config: dbConfig)
/// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.enableLogging(on: .psql)
databases.add(database: postgresql, as: .psql)
services.register(databases)
The important line being the third from the bottom. For a while I was trying to enable debugging on PostgreSQLDatabaseConfig, so to anyone in the future, take note that you're enabling it on the DatabasesConfig object instead.

Mongodb authentication using MongoCredential

I have a grails application in which Im using db.authenticate for a login page but I understand this method has been deprecated and therefore I would like to upgrade my application to using the MongoCredential object for authentication. However, unlike the db.authenticate which nicely returns a boolean to get authentication done, the MongoCredential doesn't return a boolean so how can I go about accomplishing the code replacement with minimal headache. Ideally, I'd like to derive some kind of a boolean to tell me if authentication was achieved. Thanks for your patience. Im a newbie with Mongodb.
This is part of the code I need to replace which currently makes use of the deprecated method "authenticate":
MongoClient mongoClient = new MongoClient("localhost", 27017)
DB db = mongoClient.getDB("twcdb");
def userName = params.username
def passWord = params.password
//deprecated method being used in the line below.
boolean auth = db.authenticate(userName, passWord.toCharArray())
if (auth) {
userloggedin = params.username
render(contentType: 'text/json') {
[success: true, url: createLink(controller: 'admin', action: 'loggedin')]
}
}
else {
render(contentType: 'text/json') {
["success": false, "message": 'Login or Password is incorrect.']
}
Edit: I know that the answer must lie in testing a property of the MongoClient object somehow to see if it contains a valid authenticated connection but I am still stuck on how to do this. Given I knowingly feed the MongoClient constructor with a bogus MongoCredential, it still creates an object that isn't null. I was betting on the null test but no joy. So, how do I replace the deprecated db.authenticate?