Slick: Return inserted row with auto increment id - mysql

I'm trying to make an insert into a MySQL table and to return the row with the auto increment id. My code is below:
private val Log = TableQuery[GCMLogTable]
def save(log: GCMLog): Try[GCMLog] = Try {
val newId = (Log returning Log.map(_.id)) += log
log.copy(id = newId)
}
But my compilation fails for my code with the below error:
type mismatch;
found : slick.profile.FixedSqlAction[Long,slick.dbio.NoStream,slick.dbio.Effect.Write]
required: Long
Also tried
def save(log: GCMLog): Try[GCMLog] = Try {
(Log returning Log.map(_.id)
into ((log, newId) => log.copy(id = newId))
) += log
}
But still fails with
type mismatch;
found : slick.profile.FixedSqlAction[models.GCMLog,slick.dbio.NoStream,slick.dbio.Effect.Write]
required: models.GCMLog
[I referred the SO question How to catch slick postgres exceptions for duplicate key value violations and Slick documentation here http://slick.typesafe.com/doc/3.1.1/queries.html ]
Much appreciated if someone can tell me what's going on and how this can be fixed.
Thanks!

def save(log: GCMLog): Try[GCMLog] = Try {
(Log returning Log.map(_.id))
into ((log, newId) => log.copy(id = newId))
) += log
}
UPDATE:
It looks db.run needs to be perform to convert that Action into result.

slick supports it:
def create(objectToCreate: MyCaseClass): MyCaseClass = {
db.withSession {
(self returning self) += objectToCreate
}
}

Try this
private val Log = TableQuery[GCMLogTable]
private val db = Database.forConfig("mysql")
def save(log: GCMLog): Try[GCMLog] = Try {
val newId = db.run((Log returning Log.map(_.id) into ((Log,id) => Log.copy(id=id))) += log)
Await.result(newId, Duration.Inf)
}

Related

Batch json strings processing using playframework in Scala

I use API which might either return a single json string, a batch of json strings or the string PROCESSING_TIMEOUT, e.g.:
{"id":123,"field1":"test1"}
or:
{"id":123,"field1":"test1"}
{"id":456,"field2":"test2"}
{"id":789,"field3":"test3"}
or (in case of asynchronous processing timeout in remote API)
PROCESSING_TIMEOUT
In the function getRestContent I want to be able to correcty process all these possible outputs, including also the timeout errors. In the current version of the function I lack the possibility to process batch json strings. I think that the best option would be that the function returns List<JsValue> instead of JsValue.
How can I do this modification using Play Framework.
def getRestContent(url:String,param:String,paramValue:String): JsValue = {
var output : JsValue = null
var httpOutput : String = null
try {
val response: HttpResponse[String] = Http(url).timeout(connTimeoutMs = 10000000, readTimeoutMs = 10000000).param(param,paramValue).asString
httpOutput = response.body
} catch
{
case ex: Exception => {
println("Failed connection with remote API")
}
}
if (!httpOutput.contains("PROCESSING_TIMEOUT") && httpOutput != null)
{
try {
output = Json.parse(httpOutput)
}
catch
{
case ex: Exception => {
println("Failed to process a document")
}
}
}
else
{
println("Asynchronous processing timeout")
}
if (output != null)
{
return output
}
else {
return new JsObject(Map("empty" -> JsNumber(0)))
}
}
Disregarding Play Framework your code is not Scala-flavored in general.
Below is a simple example of how better to approach such task in more Scala-way.
Highlights: use scala.util.Try wrapper to normally work with exceptions in a functional way, use pattern matching and monadic map and other methods of collections.
I hope the code below is self-explanatory. I mimicked the API. It returns Strings and not JSON but your 3 basic cases are sufficiently emulated: single line, multiple lines and exceptional case.
Try to run the program few times and you will see that all 3 cases are handled correctly:
import scala.util.{Failure, Success, Try, Random}
/**
* Created by Alex on 3/10/2016.
*/
object Temp {
case class Item(name:String, value:Int)
object API{
def getTimeOutResponse:String = throw new TimeoutException("no luck this time")
def getSingleLineResponse = "{name: \"Alex\", value: 1}"
def getMultiLineResponse = "{name: \"Alex\", value: 1}\n{name: \"HackerDuck\", value: 2}"
def getRandomResponse = (Math.abs(Random.nextInt() % 3)) match{
case 0 => getTimeOutResponse
case 1 => getSingleLineResponse
case 2 => getMultiLineResponse
}
}
def getResults:List[Item]={
Try(API.getRandomResponse) match{
case Success(s) =>{
s.split("\n").toList.map{item =>
val parts = item.split(", ")
Item(parts(0).replace("{name: ", "").replace("\"", ""), parts(1).replace("value: ", "").replace("}", "").toInt)
}
}
case Failure(_) =>{
println("API timeout happened")
List.empty[Item]
}
}
}
def main(args:Array[String])={
println(getResults)
println(getResults)
println(getResults)
}
}
A sample output from my console:
API timeout happened
List()
List(Item(Alex,1))
List(Item(Alex,1), Item(HackerDuck,2))
Process finished with exit code 0
The code becomes less cluttered without all these if statements and !=null and alike. Also you can streamline conversion of your elements sequence to List in one place.

How to return json from Play Scala controller?

I would like to know that how can I return json response data from Play(2.2.x) Scala controller class to display on my view page ? I have json objects in Postgresql database(table name: "test" and having: id and name). Please provide me any solutions for it.
I have tried the following cases(a and b), but I am not sure why I am not getting the response(like: names) on my controller, so I can show them on my view page ? since I am very new to Play/Scala and Postgresql.
case a. If I give like:
model:
def getTestValuesFromTable() = {
DB.withConnection { implicit connection =>
val selectJson =SQL("select name from test").on().apply().collect {
case Row(id:Long, Some(name:String)) =>
new TestContent(name)
}
//.head
//JsObject(selectJson().map { row => row[Long]("id").toString -> JsString(row[String]("name")) }.toSeq)
}
}
controller:
def getTest = Action {
val response = TestContent.getTestValuesFromTable()
Ok("Done")
//Ok(response)
}
Output is: Done(application is executing fine without any exceptions, of course json data is not coming since I am returning: Done only, so getting output: "Done")
case b. If I do like this: getting error: not enough arguments for method apply: (n: Int)models.Testname in trait LinearSeqOptimized. Unspecified value parameter n. I really not sure how can I get my response for it ?
controller:
def getTest = Action {
val response = TestContent.getTestValuesFromTable()
// Ok("Done")
Ok(response)
}
model:
def getTestValuesFromTable(): JsValue = {
DB.withConnection { implicit connection =>
val selectJson = SQL("select * from test")
JsObject(selectJson().map { row => row[Long]("id").toString -> JsString(row[String]("name")) }.toSeq)
// val selectJson =SQL("select name from test").on().apply().collect {
// case Row(id:Long, Some(name:String)) =>
// new TestContent(name)
// }
//.head
JsObject(selectJson().map { row => row[Long]("id").toString -> JsString(row[String]("name")) }.toSeq)//not enough arguments for method apply: (n: Int)models.Testname in trait LinearSeqOptimized. Unspecified value parameter n.
}
}
Please let me know how to get my response ?
getJsonValuesFromTable method return nothing (Unit). To fix it change definition of this method to
def getJsonValuesFromTable(testContent: TestContent) = {
or explicitly setting type:
def getJsonValuesFromTable(testContent: TestContent): Unit = {
Also as a next step to let client know that you are returning json, you should set content type:
Ok(Json.obj(response)).as("application/json")

Scala - Can I define a function that receives any function as a parameter?

Is it possible, in Scala, to define a function that would receive any other function as a parameter?
It should be something like the following:
object Module extends SecureModule{
val bc = new MyBC()
def method(parameter: Type) = {
exec(bc.method(parameter))
}
def method2(parameter1: Type1, parameter2: Type2) = {
exec(bc.method2(parameter1,parameter2))
}
}
trait SecureModule {
def exec(f: ANY_PARAMETER => ANY_RESULT) = {
//some extra processing
f
}
}
is it possible? If so, how could I achieve this?
Thank you in advance.
The nice thing about scala is that you can create what seems to be your own syntax.
If what you want to do is wrap an operation so that you can do pre and post processing, as well as control the execution context, then you do this by using call-by-name parameters. For example, if we just wanted to time how long a block of code takes, then we could do something like this:
def timer[T](block: => T): (T,Long) = {
val startDate = new Date()
val result = block
val endDate = new Date()
(result, endDate.getTime()-startDate.getTime())
}
We can use it like this:
val (result,duration) = timer {
1+3
}
Or like this
val (result,duration) = timer {
"hello" + " world!"
}
And the result will have the correct type from the block that you pass in while also giving you the duration that you expect.
I am under the impression that your description is somewhat misleading.
The way I understand it, what you (might) want to do is delaying the execution of the bc.method calls until some other code has been performed.
If so, try this:
object Module extends SecureModule{
val bc = new MyBC()
def method(parameter: Type) = {
exec(() => bc.method(parameter))
}
def method2(parameter1: Type1, parameter2: Type2) = {
exec(() => bc.method2(parameter1,parameter2))
}
}
trait SecureModule {
def exec[Result](f: () => Result): Result = {
//some extra processing
f()
}
}
You can't take any function as a parameter. What would you even do it?
At best, you can take any function that has a specific number of parameters.
For example, here, f takes one argument and returns a value.
def exec[A,B](f: A => B)
And here, f takes two arguments:
def exec[A,B,C](f: (A, B) => C)
If you don't care about the return type of the function, you could always use Any instead of a type parameter, since functions are covariant in their return type:
def exec[A](f: A => Any)

Having trouble getting Writes to work with Scala Play

To begin with I would like to say sorry for long post, and I really appreciate those who still look into my problem.
I have a controller that should return a json-response with a structure like:
{
result: [
{
key: value,
key: value,
key: value,
key: [
{
key: value,
key: value,
key: value
},...
]
},....
]
}
However I have problems getting the Writes to work as I want.
Note. I will add comments under the line where I have problem.
object APIController extends Controller {
def feed() = Action {
val objects = repo.getObjects().toList
Ok(Json.toJson(Json.obj("result" -> Class_1.apply(objects).result)))
}
first off, if I don't make a Json.obj("result" -> List[objects]) the result key isn't shown in the JSON-result. If I add a Writer for that I get errors saying that the List[objects] must have a Writer. But if I write it like above it doesn't need a Writer for the List[objects]
case class Class_1 (result: Seq[Class_2])
object Class_1 {
def apply(objs: List[Object]) = {
var result:ListBuffer[Class_2] = ListBuffer[Class_2]()
for(obj <- objs) feedResult += Class_2.apply(code)
new Class_1(result.toList)
}
}
*this is where I would put the Writer for Class_1. But if I do this like
implicit val class1Writer = new Writes[Class_1] {
override def writes(o: Class_1): JsValue = Json.obj("result" -> o.result)
} I get the problems I mentioned earlier, that I suddenly need a Writes for a List[objects] of that type*
case class Class_2 (id: Long, id2: Long, listOfStuff: Seq[Class_3])
object Class_2 {
def apply(obj: Object) = {
var items: ListBuffer[Class_3] = ListBuffer[Class_3]()
for(obj1 <- obj.getListOfStuff()) items += Class_3.apply(obj1)
new Class_2(obj.firstID, obj.secID, items.toList)
}
}
implicit val class2Writes = new Writes[Class_2] {
override def writes(o: Class_2): JsValue = {
Json.obj(
"id" -> o.id,
"id2" -> o.id2,
"items" -> o.listOfStuff
)
}
}
*the "items" -> o.listOfStuff says it needs a Writes for a List[types in the list] but I have a Writes for the objects in the list (Class_3) and I don't need a Writes for when serializing a list of objects from Class_2, why is it behaving like this?*
case class Class_3 (id: Long, text: String)
object Class_3 {
def apply(obj: Object) = {
new Class_3(obj.id, obj.funnyText)
}
}
implicit val class3Writer = new Writes[Class_3] {
override def writes(o: Class_3): JsValue = {
Json.obj(
"id" -> o.id,
"text" -> o.text
)
}
}
}
The error I get from this code is:
No Json deserializer found for type Seq[Class_3]. Try to implement an implicit Writes or Format for this type.
[error] "items" -> o.listOfStuff
[error] ^
If I remove this line in the Writes it compiles and works.
And I think that's weird since the first list I serialize doesn't have a Writer, only for the objects in the list.
Does anyone know why it behaves like this?
What should I do to accomplish what I'm after? (I hope you see what I'm trying to do)
Thanks in advance.
Just put the implicit val class3Writer ahead of class2Writes

Scala Lift - Dynamically called function

I've got a function which loads various models, and currently have this kind of setup:
if(message == "user") {
var model = User.findAll(
("room" -> "demo")
)
} else if (message == "chat") {
var model = Chat.findAll(
("room" -> "demo")
)
}
This is really clunky as I aim to add lots more models in future, I know in javascript you can do something like this:
var models = {
"user" : load_user,
"chat" : load_chat
}
Where "load_user" and "load_chat" would load the respective models, and so I can streamline the whole thing by doing:
var model = models[message]();
Is there a way I can do something similar in Scala, so I can have a simple function which just passes the "message" var to a List or Object of some kind to return the relevant data?
Thanks in advance for any help, much appreciated :)
In Scala you can do:
val model = message match {
case "user" => loadUser() // custom function
case "chat" => loadChat() // another custom function
case _ => handleFailure()
}
You can as well work with a Map like you did in your JavaScript example like so:
scala> def loadUser() = 1 // custom function
loadUser: Int
scala> def loadChat() = 2 // another custom function
loadChat: Int
scala> val foo = Map("user" -> loadUser _, "chat" -> loadChat _)
foo: scala.collection.immutable.Map[java.lang.String,() => Int] = Map(user -> <function0>, chat -> <function0>)
scala> foo("user")()
res1: Int = 1
Pay attention to the use of "_" in order to prevent evaluation of loadUser or loadChat when creating the map.
Personally, I'd stick with pattern matching.