I would like to make the prepareStatement serializable
A preparedStatement is not serializable. I have to build a serializable structure that wraps the call and the parameters to control the construction of the said statement during the deserialization
Here are the classes I created to wrap the PrepareStament
import java.sql._
import java.sql.SQLException
import java.util
import java.util.Collections
import avro.shaded.com.google.common.collect.ImmutableMap
import scala.collection.immutable.HashMap
import scala.collection.mutable
class WrappedConnection(var delegate: Connection) extends Serializable {
def prepareStatement(sql: String): WrappedPreparedStatement = {
val ps = delegate.prepareStatement(sql)
new WrappedPreparedStatement(sql, ps)
}
// delegate all Connection methods to the delegate
}
class WrappedPreparedStatement(var sql: String, var delegate: PreparedStatement) extends Serializable {
private var parameters: mutable.Map[Integer, Object] = mutable.Map.empty[Integer, Object]
override def toString: String = sql
def apply( delegateVar: PreparedStatement) {
delegate = delegateVar
parameters = mutable.Map.empty[Integer, Object]
}
def getParameters = parameters
// TODO: many methods to delegate
#throws[SQLException]
def setString(parameterIndex: Int, x: String): Unit = {
delegate.setString(parameterIndex, x)
parameters.put(parameterIndex, x)
}
#throws[SQLException]
def executeQuery = { // perhaps you might want to do some logging here?
delegate.executeQuery
}
// delegate all PreparedStatement methods to the delegate
}
object WrappedConnection {
def apply(delegate: Connection): WrappedConnection = new WrappedConnection(delegate)
}
This is the test code
val connection = MsSqlUtils.createConnectionFactory(config)
val conn = connection()
val wrapperConn = WrappedConnection(conn)
val statement = wrapperConn.prepareStatement("select * from users")
Currently, my problem is to access the variables of my prepareStatement object and create get functions that will return them.
When I talk about variables I talk about the one shown in the picture below not the one in the querie
Anyone know how to access these variables?
Related
I wrote some code which acquires some implicit values in the companion object like this:
package example.implicits
class Test {
import Test.GetValue
import Test.Implicits._
val intV = getV[Int]
val stringV = getV[String]
private def getV[T](implicit getV: GetValue[T]): T = getV.value
}
object Test {
trait GetValue[T] {
def value: T
}
object Implicits {
implicit val intValue = new GetValue[Int] {
def value = 10
}
implicit val stringValue = new GetValue[String] {
def value = "ten"
}
}
}
This piece of code cannot be compiled and the compiler complains it couldn't find the required implicit values. Note that my environment is
scala 2.11.8 on Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66
However, if I use these values explicitly, nothing goes wrong:
class Test {
import Test.GetValue
import Test.Implicits._
val intV = getV[Int](intValue)
val stringV = getV[String](stringValue)
private def getV[T](implicit getV: GetValue[T]): T = getV.value
}
Further more, if I declare new implicit values as following:
class Test {
import Test.GetValue
import Test.Implicits._
implicit val intValue1 = intValue
implicit val stringValue1 = stringValue
val intV = getV[Int]
val stringV = getV[String]
private def getV[T](implicit getV: GetValue[T]): T = getV.value
}
errors will be raised because of ambiguous implicit values.
When I swap position of class Test and object Test, everything goes right:
object Test {
trait GetValue[T] {
def value: T
}
object Implicits {
implicit val intValue = new GetValue[Int] {
def value = 10
}
implicit val stringValue = new GetValue[String] {
def value = "ten"
}
}
}
class Test {
import Test.GetValue
import Test.Implicits._
val intV = getV[Int]
val stringV = getV[String]
private def getV[T](implicit getV: GetValue[T]): T = getV.value
}
So why can't scala find implicit values after I've already imported them in the first case?
And why it can do so when I swap their position?
That's because the compiler hasn't infered the type of Test.intValue yet at the time when it resolves the implicits in getV[Int].
Just give Test.intValue and Test.stringValue their type explicitly, and your problem will be solved.
I read somewhere (sorry, can't remember where exactly), that implicit definitions should always be given an explicit type, notably to avoid this kind of behaviour.
I still get the same error, I have defined the marshaller (and imported it); it appears that the case class entry is not in context when the function is polymorphic. and this throws a Cannot find JsonWriter or JsonFormat type class for Case Class. Is there a reason why spray-json can not find the implicit marshaller for the case class, (even when defined) is this case class in context? Link to marshaller
import spray.json._
import queue.MedusaJsonProtocol._
object MysqlDb {
...
}
case class UserDbEntry(
id: Int,
username: String,
countryId: Int,
created: LocalDateTime
)
trait MysqlDb {
implicit lazy val pool = MysqlDb.pool
}
trait HydraMapperT extends MysqlDb {
val FetchAllSql: String
def fetchAll(currentDate: String): Future[List[HydraDbRow]]
def getJson[T](row: T): String
}
object UserHydraDbMapper extends HydraMapperT {
override val FetchAllSql = "SELECT * FROM user WHERE created >= ?"
override def fetchAll(currentDate: String): Future[List[UserDbEntry]] = {
pool.sendPreparedStatement(FetchAllSql, Array(currentDate)).map { queryResult =>
queryResult.rows match {
case Some(rows) =>
rows.toList map (x => rowToModel(x))
case None => List()
}
}
}
override def getJson[UserDbEntry](row: UserDbEntry): String = {
HydraQueueMessage(
tableType = HydraTableName.UserTable,
payload = row.toJson.toString()
).toJson.toString()
}
private def rowToModel(row: RowData): UserDbEntry = {
UserDbEntry (
id = row("id").asInstanceOf[Int],
username = row("username").asInstanceOf[String],
countryId = row("country_id").asInstanceOf[Int],
created = row("created").asInstanceOf[LocalDateTime]
)
}
}
payload = row.toJson.toString() Can't find marshaller for UserDbEntry
You have defined UserDbEntry locally and there is no JSON marshaller for that type. Add the following:
implicit val userDbEntryFormat = Json.format[UserDbEntry]
I'm not sure how you can call row.toJson given UserDbEntry is a local case class. There must be a macro in there somewhere, but it's fairly clear that it's not in scope for the local UserDbEntry.
Edit
Now that I see your Gist, it looks like you have a package dependency problem. As designed, it'll be circular. You have defined the JSON marshaller in package com.at.medusa.core.queue, which imports UserDbEntry, which depends on package com.at.medusa.core.queue for marshalling.
I'm trying implement section 17.9 Workers in Scala by Example book with Scala version 2.11.7.
Import statements:
import scala.concurrent._, scala.concurrent.ops._
was error "ops not is member of scala.concurrent". I did google and known that concurrent.ops is deprecated and rather by future, change import statement to:
import scala.concurrent._, scala.concurrent.Future._
Entire class source:
import scala.concurrent._
import scala.concurrent.Future._
class ComputeServer(n: Int) {
private abstract class Job {
type T
def task: T
def res(x: T)
}
private val openJobs = new Channel[Job]()
private def processor(i: Int) {
while(true) {
val job = openJobs.read
job.res(job.task)
}
}
def future[A](p: => A): () => A = {
val reply = new SyncVar[A]()
openJobs.write{
new Job{
type T = A
def task = p
def res(x: A) = reply.put(x)
}
}
() => reply.get
}
spawn(replicate(0, n){processor})
}
But occurs errors in line: spawn(replicate(0, n){processor})
not found: value spawn
not found: value replicate
missing arguments for method processor in class ComputeServer; follow this method with `_' if you want to treat it as a partially applied function
What're spawn, replicate, processor function in version 2.11.7?
one can create method spawn like this:
def spawn(p: => Unit) {
val t = new Thread() { override def run() = p }
t.start()
}
I'm using Play framework btw. Slick does not help you "create" tables. Users have to create it by themselves, using tableQuery.ddl.create. When it was still Slick 1.0, I read a post about creating a Global.scalaand inside it looks like this:
import play.api._
import scala.slick.jdbc.meta.MTable
import play.api.Play.current
import play.api.db.slick._
import models.current.dao._
import models.current.dao.profile.simple._
object Global extends GlobalSettings {
override def onStart(app: Application) {
DB.withSession {implicit rs =>
databaseCreate(Articles, Labels, Article_Labels, Users, Messages)
def databaseCreate(tables: TableQuery[_]*) = {
for (table <- tables)
if (MTable.getTables(table.toString).list.isEmpty) table.ddl.create
}
}
}
}
However, since it is Slick 2.0 and I'm using the Cake pattern, this doesn't work anymore. I used to be able to pull Table class out and there is an attribute called name which I can call, but now with the new and improved Cake pattern, all I'm left with is TableQuery, which literally has nothing. (Cake pattern example is here: https://github.com/slick/slick-examples/blob/master/src/main/scala/com/typesafe/slick/examples/lifted/MultiDBCakeExample.scala)
My DAO class looks like this:
class DAO(override val profile: JdbcProfile) extends ArticleComponent with Article_LabelComponent with LabelComponent with MessageComponent with UserComponent with Profile {
val Articles = TableQuery[Articles]
val Article_Labels = TableQuery[Article_Labels]
val Labels = TableQuery[Labels]
val Messages = TableQuery[Messages]
val Users = TableQuery[Users]
}
object current {
val dao = new DAO(DB(play.api.Play.current).driver)
}
How should I modify my Global.scala to create a table if a table is not present in the Database?
take a look : http://blog.knoldus.com/2014/01/20/scala-slick-2-0-for-multi-database/
and you can put directly ddl create statement in Glabal.scala:
object Global extends GlobalSettings
override def onStart(app: Application): Unit = {
Logger.info("Apllication has started")
try {
Connection.databaseObject.withSession { implicit session: Session =>
(Articles.ddl ++ Article_Labels.ddl ++ Labels.ddl ++ Messages.ddl ++ Users.ddl).create
Logger.info("All tables have been created")
} catch {
case ex: Exception => Logger.info(ex.getMessage() + ex.printStackTrace())
}
}
}
define connection object:
object Connection {
def databaseObject(): Database = {
Database.forDataSource(DB.getDataSource())
}
}
As far as I understand it, Scala creates an anonymous class if I create a class using the new keyword and follow the class name with a constructor:
class MyClass {
def doStuff() {
// ...
}
}
val mc = new MyClass {
doStuff()
}
The nice thing being that all the code in the constructor is in the scope of the new object.
Is there a way I can reproduce this syntax where the class is created by a factory method rather than the new keyword? i.e. make the following code work:
val mf = new MyFactory
val mc = mf.MyClass {
doStuff()
}
I can't find a way to do it but Scala has so much to it that this might be pretty easy!
Using an import as suggested by #Ricky below I can get:
val mf = MyFactory;
val mc = mf.MyClass
{
import mc._
doStuff()
}
(Where the blank line before the block is needed) but that code block is not a constructor.
You can do this, but you still have to keep the new keyword, and create the nested class as a path-dependent type:
class Bippy(x: Int) {
class Bop {
def getIt = x
}
}
val bip = new Bippy(7)
val bop = new bip.Bop
bop.getIt // yields 7
val bop2 = new bip.Bop{ override def getIt = 42 }
bop2.getIt // yields 42
I don't think it's possible. However, a common pattern is to add a parameter to factory methods which takes a function modifying the created object:
trait MyClass {
var name = ""
def doStuff():Unit
}
class Foo extends MyClass {
def doStuff() { println("FOO: " + name) }
}
trait MyClassFactory {
def make: MyClass
def apply( body: MyClass => Unit ) = {
val mc = make
body(mc)
mc
}
}
object FooFactory extends MyClassFactory {
def make = new Foo
}
You can then create and modify instance with a syntax close to your example:
val foo = FooFactory { f=>
f.name = "Joe"
f.doStuff
}
It sounds like you're just looking to mix in a trait. Instead of calling myFactoryMethod(classOf[Foo]] which ideally would do (if Scala permitted it):
new T {
override def toString = "My implementation here."
}
you can instead write
trait MyImplementation {
override def toString = "My implementation here."
}
new Foo with MyImplementation
However, if you are just looking to get the members of the new object accessible without qualification, remember you can import from any stable identifier:
val foo = new Bar
import foo._
println(baz) //where baz is a member of foo.