I am trying to write a play! framework 2.1 application with ReactiveMongo, following this sample. however, with every call to the plugin, it seems that the application hangs after the operation completes, than the pluging closes and restarts, and we move on. functionality work, but i am not sure if it's not crashing and restarting along the way.
code:
def db = ReactiveMongoPlugin.db
def nodesCollection = db("nodes")
def index = Action {implicit request =>
Async {
Logger.debug("serving nodes list")
implicit val nodeReader = Node.Node7BSONReader
val query = BSONDocument(
"$query" -> BSONDocument()
)
val found = nodesCollection.find(query)
found.toList.map { nodes =>
Logger.debug("returning nodes list to requester")
Ok(views.html.nodes.nodes(nodes))
}
}
}
def showCreationForm = Action { implicit request =>
Ok(views.html.nodes.editNode(None, Node.nodeCredForm))
}
def create = Action { implicit request =>
Node.nodeCredForm.bindFromRequest.fold(
errors => {
Ok(views.html.nodes.editNode(None, errors))
},
node => AsyncResult {
Node.createNode(node._1, node._2, node._3) match {
case Right(myNode) => {
nodesCollection.insert(myNode).map { _ =>
Redirect(routes.Nodes.index).flashing("success" -> "Node Added")
}
}
case Left(message) => {
Future(Redirect(routes.Nodes.index).flashing("error" -> message))
}
}
}
)
}
logging:
[debug] application - in Node constructor
[debug] application - done inseting, redirecting to nodes page
--- (RELOAD) ---
[info] application - ReactiveMongoPlugin stops, closing connections...
[info] application - ReactiveMongo stopped. [Success(Closed)]
[info] application - ReactiveMongoPlugin starting...
what is wrong with this picture?
There seems nothing wrong with that picture. If you only showed me that log output I would say you would have changed a file in you play application. Which would cause the application to reload.
I guess that is not the case, so your database is probably located within your application directory, causing the application to reload on each change. Where is your database located?
Related
I'm new to Akka-Http. I added following Route
path(urlpath / "messages") {
post {
decodeRequest {
withoutSizeLimit {
entity(asSourceOf[Message]) { source =>
val storeToDb = Flow[Message].map[Future[Message]](message => (service ask message).mapTo[Message])
val sendToProviderFlow = Flow[Future[Message]].map[Unit](message => sendToJasminProvider(message))
val futureResponse = source
.via(storeToDb)
.via(sendToProviderFlow)
.runWith(Sink.ignore).map(_ => "Message Received")
complete(futureResponse)
}
}
}
}
}
When I tried run above Route, I've been receiving couple of errors and I do not know how to fix them.
Issues:
Accept error: could not accept new connection java.io.IOException: Too many open files
[1] dead letters encountered. If this is not an expected behavior,This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
akka.http.scaladsl.model.EntityStreamException: Entity stream
truncation
About first error, it's seems that you open too many connection. Maybe you simply didn't close them somewhere. Unix used similar connection for sockets and files
About second error, it's obvious that your actor (service) is dead. Try to debug your actors lifecycle and start with
enabling akka.actor.debug.lifecycle = on
For more details visit this page
https://doc.akka.io/docs/akka/current/logging.html#auxiliary-logging-options
Is sendToJasminProvider has type Future[Message] => Unit? If that function has type like Future[Message] => Future[T] then it's problem
The play example for using Oauth and Twitter is show below.
In the Play Framework I am still learning how to use redirects and routes. How would you set up the routes file and the Appliction.scala file to handle this redirect?
Redirect(routes.Application.index).withSession("token" -> t.token, "secret" -> t.secret)
Would the routes be something like this?
GET /index controllers.Application.index(String, String)
Link to Play Framework documentation with the example code http://www.playframework.com/documentation/2.0/ScalaOAuth
object Twitter extends Controller {
val KEY = ConsumerKey("xxxxx", "xxxxx")
val TWITTER = OAuth(ServiceInfo(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize", KEY),
false)
def authenticate = Action { request =>
request.queryString.get("oauth_verifier").flatMap(_.headOption).map { verifier =>
val tokenPair = sessionTokenPair(request).get
// We got the verifier; now get the access token, store it and back to index
TWITTER.retrieveAccessToken(tokenPair, verifier) match {
case Right(t) => {
// We received the authorized tokens in the OAuth object - store it before we proceed
Redirect(routes.Application.index).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
}
}.getOrElse(
TWITTER.retrieveRequestToken("http://localhost:9000/auth") match {
case Right(t) => {
// We received the unauthorized tokens in the OAuth object - store it before we proceed
Redirect(TWITTER.redirectUrl(t.token)).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
})
}
def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}
}
It turned out that the reasons I had so many intermittent problems with routes and redirect was a combination of the versions of play, version of scala and the version of ScalaIDE for Eclipse. Using Play version 2.2.3, scala version 2.10.4 and ScalaIDE version 2.10.x solved the routes and redirect problems.
The following import statements are needed for the Twitter example.
import play.api.libs.oauth.ConsumerKey
import play.api.libs.oauth.ServiceInfo
import play.api.libs.oauth.OAuth
import play.api.libs.oauth.RequestToken
If your route is like this:
GET /index controllers.Application.index(param1:String, param2:String)
Then the reverse route would look like this:
routes.Application.index("p1", "p2")
Which would result in something like this:
/index?param1=p1¶m2=p2
Make sure that the documentation you are looking at is of the correct version, for 2.2.x you would need this url: http://www.playframework.com/documentation/2.2.x/ScalaOAuth
I have been working on this issue for quite a while now and I cannot find a solution...
A web app built with play framework 2.2.1 using h2 db (for dev) and a simple Model package.
I am trying to implement a REST JSON endpoint and the code works... but only once per server instance.
def createOtherModel() = Action(parse.json) {
request =>
request.body \ "name" match {
case _: JsUndefined => BadRequest(Json.obj("error" -> true,
"message" -> "Could not match name =(")).as("application/json")
case name: JsValue =>
request.body \ "value" match {
case _: JsUndefined => BadRequest(Json.obj("error" -> true,
"message" -> "Could not match value =(")).as("application/json")
case value: JsValue =>
// this breaks the secod time
val session = ThinkingSession.dummy
val json = Json.obj(
"content" -> value,
"thinkingSession" -> session.id,
)
)
Ok(Json.obj("content" -> json)).as("application/json")
}
} else {
BadRequest(Json.obj("error" -> true,
"message" -> "Name was not content =(")).as("application/json")
}
}
}
so basically I read the JSON, echo the "value" value, create a model obj and send it's id.
the ThinkingSession.dummy function does this:
def all(): List[ThinkingSession] = {
// Tried explicitly closing connection, no difference
//val conn = DB.getConnection()
//try {
// DB.withConnection { implicit conn =>
// SQL("select * from thinking_session").as(ThinkingSession.DBParser *)
// }
//} finally {
// conn.close()
//}
DB.withConnection { implicit conn =>
SQL("select * from thinking_session").as(ThinkingSession.DBParser *)
}
}
def dummy: ThinkingSession = {
(all() head)
}
So this should do a SELECT * FROM thinking_session, create a model obj list from the result and return the first out of the list.
This works fine the first time after server start but the second time I get a
play.api.Application$$anon$1: Execution exception[[SQLException: Timed out waiting for a free available connection.]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.1]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
Caused by: java.sql.SQLException: Timed out waiting for a free available connection.
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:88) ~[bonecp.jar:na]
at com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90) ~[bonecp.jar:na]
at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:553) ~[bonecp.jar:na]
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:131) ~[bonecp.jar:na]
at play.api.db.DBApi$class.getConnection(DB.scala:67) ~[play-jdbc_2.10.jar:2.2.1]
at play.api.db.BoneCPApi.getConnection(DB.scala:276) ~[play-jdbc_2.10.jar:2.2.1]
My application.conf (db section)
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:file:database/[my_db]"
db.default.logStatements=true
db.default.idleConnectionTestPeriod=5 minutes
db.default.connectionTestStatement="SELECT 1"
db.default.maxConnectionAge=0
db.default.connectionTimeout=10000
Initially the only thing set in my config was the connection and the error occurred. I added all the other stuff while reading up on the issue on the web.
What is interesting is that when I use the h2 in memory db it works once after server start and after that it fails. when I use the h2 file system db it only works once, regardless of the server instances.
Can anyone give me some insight on this issue? Have found some stuff on bonecp problem and tried upgrading to 0.8.0-rc1 but nothing changed... I am at a loss =(
Try to set a maxConnectionAge and idle timeout
turns out the error was quite somewhere else... it was a good ol' stack overflow... have not seen one in a long time. I tried down-voting my question but it's not possible^^
I'm using Specs2 to test my Scalatra web service.
class APISpec extends ScalatraSpec {
def is = "Simple test" ^
"invalid key should return status 401" ! root401^
addServlet(new APIServlet(),"/*")
def root401 = get("/payments") {
status must_== 401
}
}
This tests the web service locally (localhost). Now I would like to perform the same tests to the production Jetty server. Ideally, I would be able to do this by only changing some URL. Is this possible at all ? Or do I have to write my own (possible duplicate) testing code for the production server?
I don't know how Scalatra manages its URLs but one thing you can do in specs2 is control parameters from the command-line:
class APISpec extends ScalatraSpec with CommandLineArguments { def is = s2"""
Simple test
invalid key should return status 401 $root401
${addServlet(new APIServlet(),s"$baseUrl/*")}
"""
def baseUrl = {
// assuming that you passed 'url www.production.com' on the command line
val args = arguments.commandLine.split(" ")
args.zip(args.drop(1)).find { case (name, value) if name == "url" => value }.
getOrElse("localhost:8080")
}
def root401 = get(s"$baseUrl/payments") {
status must_== 401
}
}
When working locally I have no problem testing my application by calling:
http://localhost:9000/r/123
method:
def showSurvey(id: String) = Action {
implicit val reader = Review.ReviewReader
Async {
val cursor = reviews.find(BSONDocument("_id" -> BSONObjectID(id))).cursor[Review]
cursor.headOption.map(maybeReview =>
maybeReview.map(review => {
// fill form
Ok(views.html.review.desktopSurvey(Some(id), surveyForm.fill(SurveyForm(review.grade, review.text, REGULAR_AUTH, false, "", "")), grades))
}
).getOrElse {
//NotFound Temporary below:
val review = Review(Some(new BSONObjectID(id)), 3, "bla", Some(new DateTime()), Some(new DateTime()), Some("0.0.0.0"), ReviewStatus.NOT_CLAIMED, Some(1), Some(1L))
Ok(views.html.review.desktopSurvey(Some(id), surveyForm.fill(SurveyForm(review.grade, review.text, REGULAR_AUTH, false, "", "")), grades))
}
).recover {
case e => InternalServerError(e.getMessage())
}
}
}
But when running the app in production by doing clean compile stage and then going to the
url I get:
[error] r.c.a.MongoDBSystem - The entire node set is unreachable, is there a network problem?
I find this very strange since the plugin seems to work properly:
[info] application - ReactiveMongoPlugin successfully started with db 'blala'! Servers:
[87.238.57.140:27017]
By checking the mongodb log i found that the connection was ok but the bson sent in was invalid:
Tue May 21 11:18:11.257 [conn531] Assertion: 10307:Client Error: bad object in message: invalid bson
0xdcf361 0xd90a1b 0xd90f5c 0x75b289 0x75b3fb 0x9f4367 0x9f57e2 0x6e747a 0xdbbb7e 0x7fa22e96d9ca 0x7fa22dd14cdd
/usr/bin/mongod(_ZN5mongo15printStackTraceERSo+0x21) [0xdcf361]
/usr/bin/mongod(_ZN5mongo11msgassertedEiPKc+0x9b) [0xd90a1b]
/usr/bin/mongod() [0xd90f5c]
/usr/bin/mongod(_ZN5mongo9DbMessage9nextJsObjEv+0x249) [0x75b289]
/usr/bin/mongod(_ZN5mongo12QueryMessageC1ERNS_9DbMessageE+0x8b) [0x75b3fb]
/usr/bin/mongod() [0x9f4367]
/usr/bin/mongod(_ZN5mongo16assembleResponseERNS_7MessageERNS_10DbResponseERKNS_11HostAndPortE+0x392) [0x9f57e2]
/usr/bin/mongod(_ZN5mongo16MyMessageHandler7processERNS_7MessageEPNS_21AbstractMessagingPortEPNS_9LastErrorE+0x9a) [0x6e747a]
/usr/bin/mongod(_ZN5mongo17PortMessageServer17handleIncomingMsgEPv+0x42e) [0xdbbb7e]
/lib/libpthread.so.0(+0x69ca) [0x7fa22e96d9ca]
/lib/libc.so.6(clone+0x6d) [0x7fa22dd14cdd]
Tue May 21 11:18:11.261 [conn531] AssertionException handling request, closing client connection: 10307 Client Error: bad object in message: invalid bson
This made me look at the code and the problem was that I was sending in an invalid ObjectId, in my case 123 . Somehow this error got swallowed by my application. So when there is a possibility that the ObjectId sent in might be corrupt check it with:
val maybeOID: Try[BSONObjectID] = BSONObjectID.parse(id)
if (maybeOID.isSuccess) {
// Do stuff
}