Scala: JavaFx Tableview does not display data - scala

So I have tried to load in some data into my Tableview but it doesnt work because every time I start my application the tableview is empty but it doesn't show the prompt message that its actually empty.
My Code:
#FXML var anchorpane: AnchorPane = _
// Example for the Product Entity
#FXML var tableview: TableView[Product] = _
#FXML var c1: TableColumn[Product,Integer] = _
#FXML var c2: TableColumn[Product,String] = _
#FXML var c3: TableColumn[Product,Double] = _
//create data for inserting in an observerList
val data: ObservableList[Product] = FXCollections.observableArrayList(
new Product(55,"hallo",33.0)
new Product(10,"hello",20.3)
)
override def initialize(location: URL, resources: ResourceBundle): Unit = {
//Für die columns namen setzen
c1.setCellValueFactory(new PropertyValueFactory[Product,Integer]("id"))
c2.setCellValueFactory(new PropertyValueFactory[Product,String]("name"))
c3.setCellValueFactory(new PropertyValueFactory[Product,Double]("price"))
//inserting data from the observableArrayList
tableview.setItems(data)
}
But my tableview remains empty...
Here is how it looks like:
My Product class:
package fhj.swengb.homework.dbtool
import java.sql.{ResultSet, Connection, Statement}
import scala.collection.mutable.ListBuffer
/**
* Created by loete on 27.11.2015.
*/
object Product extends Db.DbEntity[Product] {
val dropTableSql = "drop table if exists product"
val createTableSql = "create table product (id integer, name string, price double)"
val insertSql = "insert into product (id, name, price) VALUES (?, ?, ?)"
def reTable(stmt: Statement): Int = {
stmt.executeUpdate(Product.dropTableSql)
stmt.executeUpdate(Product.createTableSql)
}
def toDb(c: Connection)(p: Product): Int = {
val pstmt = c.prepareStatement(insertSql)
pstmt.setInt(1, p.id)
pstmt.setString(2, p.name)
pstmt.setDouble(3, p.price)
pstmt.executeUpdate()
}
def fromDb(rs: ResultSet): List[Product] = {
val lb: ListBuffer[Product] = new ListBuffer[Product]()
while (rs.next()) lb.append(Product(rs.getInt("id"), rs.getString("name"), rs.getDouble("price")))
lb.toList
}
def queryAll(con: Connection): ResultSet = query(con)("select * from product")
}
case class Product(id:Int, name: String, price:Double) extends Db.DbEntity[Product] {
def reTable(stmt: Statement): Int = 0
def toDb(c: Connection)(t: Product): Int = 0
def fromDb(rs: ResultSet): List[Product] = List()
def dropTableSql: String = "drop table if exists product"
def createTableSql: String = "create table product (id integer, name String, price Double"
def insertSql: String = "insert into person (id, name, price) VALUES (?, ?, ?)"
}

Related

how to insert usert defined type in cassandra by using lagom scala framework

I am using Lagom(scala) framework and i could find any way to save scala case class object in cassandra with has complex Type. so how to i insert cassandra UDT in Lagom scala. and can any one explain hoe to use BoundStatement.setUDTValue() method.
I have tried to do by using com.datastax.driver.mapping.annotations.UDT.
but does not work for me. I have also tried com.datastax.driver.core
Session Interface. but again it does not.
case class LeadProperties(
name: String,
label: String,
description: String,
groupName: String,
fieldDataType: String,
options: Seq[OptionalData]
)
object LeadProperties{
implicit val format: Format[LeadProperties] = Json.format[LeadProperties]
}
#UDT(keyspace = "leadpropertieskeyspace", name="optiontabletype")
case class OptionalData(label: String)
object OptionalData {
implicit val format: Format[OptionalData] = Json.format[OptionalData]
}
my query:----
val optiontabletype= """
|CREATE TYPE IF NOT EXISTS optiontabletype(
|value text
|);
""".stripMargin
val createLeadPropertiesTable: String = """
|CREATE TABLE IF NOT EXISTS leadpropertiestable(
|name text Primary Key,
|label text,
|description text,
|groupname text,
|fielddatatype text,
|options List<frozen<optiontabletype>>
);
""".stripMargin
def createLeadProperties(obj: LeadProperties): Future[List[BoundStatement]] = {
val bindCreateLeadProperties: BoundStatement = createLeadProperties.bind()
bindCreateLeadProperties.setString("name", obj.name)
bindCreateLeadProperties.setString("label", obj.label)
bindCreateLeadProperties.setString("description", obj.description)
bindCreateLeadProperties.setString("groupname", obj.groupName)
bindCreateLeadProperties.setString("fielddatatype", obj.fieldDataType)
here is the problem I am not getting any method for cassandra Udt.
Future.successful(List(bindCreateLeadProperties))
}
override def buildHandler(): ReadSideProcessor.ReadSideHandler[PropertiesEvent] = {
readSide.builder[PropertiesEvent]("PropertiesOffset")
.setGlobalPrepare(() => PropertiesRepository.createTable)
.setPrepare(_ => PropertiesRepository.prepareStatements)
.setEventHandler[PropertiesCreated](ese ⇒
PropertiesRepository.createLeadProperties(ese.event.obj))
.build()
}
I was faced with the same issue and solve it following way:
Define type and table:
def createTable(): Future[Done] = {
session.executeCreateTable("CREATE TYPE IF NOT EXISTS optiontabletype(filed1 text, field2 text)")
.flatMap(_ => session.executeCreateTable(
"CREATE TABLE IF NOT EXISTS leadpropertiestable ( " +
"id TEXT, options list<frozen <optiontabletype>>, PRIMARY KEY (id))"
))
}
Call this method in buildHandler() like this:
override def buildHandler(): ReadSideProcessor.ReadSideHandler[FacilityEvent] =
readSide.builder[PropertiesEvent]("PropertiesOffset")
.setPrepare(_ => prepare())
.setGlobalPrepare(() => {
createTable()
})
.setEventHandler[PropertiesCreated](processPropertiesCreated)
.build()
Then in processPropertiesCreated() I used it like:
private val writePromise = Promise[PreparedStatement] // initialized in prepare
private def writeF: Future[PreparedStatement] = writePromise.future
private def processPropertiesCreated(eventElement: EventStreamElement[PropertiesCreated]): Future[List[BoundStatement]] = {
writeF.map { ps =>
val userType = ps.getVariables.getType("options").getTypeArguments.get(0).asInstanceOf[UserType]
val newValue = userType.newValue().setString("filed1", "1").setString("filed2", "2")
val bindWriteTitle = ps.bind()
bindWriteTitle.setString("id", eventElement.event.id)
bindWriteTitle.setList("options", eventElement.event.keys.map(_ => newValue).toList.asJava) // todo need to convert, now only stub
List(bindWriteTitle)
}
}
And read it like this:
def toFacility(r: Row): LeadPropertiesTable = {
LeadPropertiesTable(
id = r.getString(fId),
options = r.getList("options", classOf[UDTValue]).asScala.map(udt => OptiontableType(field1 = udt.getString("field1"), field2 = udt.getString("field2"))
)
}
My prepare() function:
private def prepare(): Future[Done] = {
val f = session.prepare("INSERT INTO leadpropertiestable (id, options) VALUES (?, ?)")
writePromise.completeWith(f)
f.map(_ => Done)
}
This is not a very well written code, but I think will help to proceed work.

Updating table with enum

Trying to insert the information into DB that looks like this:
(UUID, EnumType)
with following logic:
var t = TestTable.query.map(t=> (t.id, t.enumType)) ++= toAdd.map(idTest, enumTest)))
but compiler throws an error for TestTable.query.map(t=> (t.id, t.enumType)) it's interpriting it as type Iteratable[Nothing], am I missing something?
Test table looks like this:
object TestTable {
val query = TableQuery[TestTable]
}
class TestTable(tag: slick.lifted.Tag) extends Table[TestTable](tag, "test_table") {
val id = column[UUID]("id")
val enumType = column[EnumType]("enumType")
override val * = (id, testType) <> (
(TestTable.apply _).tupled,
TestTable.unapply
)
Suppose you have following data structure:
object Color extends Enumeration {
val Blue = Value("Blue")
val Red = Value("Red")
val Green = Value("Green")
}
case class MyType(id: UUID, color: Color.Value)
Define slick schema as following:
class TestTable(tag: slick.lifted.Tag) extends Table[MyType](tag, "test_table") {
val id = column[UUID]("id")
val color = column[Color.Value]("color")
override val * = (id, color) <> ((MyType.apply _).tupled, MyType.unapply)
}
object TestTable {
lazy val query = TableQuery[TestTable]
}
To map enum to SQL data type slick requires implicit MappedColumnType:
implicit val colorTypeColumnMapper: JdbcType[Color.Value] = MappedColumnType.base[Color.Value, String](
e => e.toString,
s => Color.withName(s)
)
Now you can insert values into DB in this way:
val singleInsertAction = TestTable.query += MyType(UUID.randomUUID(), Color.Blue)
val batchInsertAction = TestTable.query ++= Seq(
MyType(UUID.randomUUID(), Color.Blue),
MyType(UUID.randomUUID(), Color.Red),
MyType(UUID.randomUUID(), Color.Green)
)

Scala slick sort by column string name

I'm trying to implement such method in slick:
def paged(page: Long, sorting: String, order: String) = {
infos.sortBy(_.???).drop((page - 1)*INFOS_PER_PAGE).take(INFOS_PER_PAGE).result
}
But I don't know what to put in sortBy and how to cast String to column.
I tried simple function like this:
class PaymentInfoTable(tag: Tag) extends Table[PaymentInfo](tag, "payment_info") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def date = column[DateTime]("date")
def paymentType = column[String]("payment_type")
def category = column[String]("category")
def subCategory = column[String]("sub_category")
def value = column[BigDecimal]("value")
def comment = column[Option[String]]("comment")
def outsidePaypal = column[Boolean]("outside_paypal")
def outsidePayer = column[Option[String]]("outside_payer")
def sorting(col: String) = {
if(col == "id") {
id
} else if (col == "date") {
date
} else if (col == "paymentType") {
paymentType
} else if (col == "category") {
category
} else if (col == "subCategory") {
subCategory
} else if (col == "value") {
value
} else if (col == "comment") {
comment
} else if (col == "outsidePaypal") {
outsidePaypal
} else if (col == "outsidePayer") {
outsidePayer
} else {
id
}
}
but then I can't do
sortBy(_.sorting(sorting).asc)
It says
value asc is not a member of slick.lifted.Rep[_1]
And I have imported
import slick.jdbc.MySQLProfile.api._
How can I sort by string column name?
Basically what you can do is to add a map with the string/property of the table
class ColorsTable(tag: Tag) extends Table[Color](tag, "color") with DynamicSortBySupport.ColumnSelector {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = (id, name) <> ((Color.apply _).tupled, Color.unapply)
val select = Map(
"id" -> (this.id),
"name" -> (this.name)
)
}
Then you only need to access that map
case ((sortColumn, sortOrder), queryToSort) =>
val sortOrderRep: Rep[_] => Ordered = ColumnOrdered(_, Ordering(sortOrder))
val sortColumnRep: A => Rep[_] = _.select(sortColumn)
queryToSort.sortBy(sortColumnRep)(sortOrderRep)
You can find more info in this, like, but not same, question Dynamic order by in scala slick with several columns
If you want something more simple, then just create an Order column with your column
if(col == "id") {
ColumnOrdered(id, Ordering(sortOrder))
}

Scala Test: File upload with additional attributes - MultipartFormData

I am actually trying to test the creation of a new product.
One attribute of a product is a picture. This picture should be stored into a directory called "images". In the database only the file name should be stored as a string in the picture column.
So I tried to create a MultiPartFormData Fake Request and add the attributes into the dataParts attribute of the MultiPartFormData.
But when executing the test i get following error:
\test\InventoryControllerSpec.scala:50: Cannot write an instance of play.api.mvc.MultipartFormData[play.api.
libs.Files.TemporaryFile] to HTTP response. Try to define a Writeable[play.api.mvc.MultipartFormData[play.api.libs.Files.TemporaryFile]]
The product model looks like following:
case class Product(id: Option[Int],
name: String,
category: String,
picture: Option[String],
amount: Int,
criticalAmount: Int
) {
}
object Product {
implicit val productFormat = Json.format[Product]
def tupled(t: (Option[Int], String, String, Option[String], Int, Int)) =
Product(t._1, t._2, t._3, t._4, t._5, t._6)
def toTuple(p: Product) = Some((p.id, p.name, p.category, p.picture, p.amount, p.criticalAmount))
}
The database model looks like this:
class Products(tag: Tag) extends Table[Product](tag, "PRODUCTS"){
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def name = column[String]("NAME")
def category = column[String]("CATEGORY")
def picture = column[String]("PICTURE")
def amount = column[Int]("AMOUNT")
def criticalAmount = column[Int]("CRITICALAMOUNT")
def * = (id.?, name, category, picture.?, amount, criticalAmount) <>(Product.tupled, Product.toTuple)
}
I think also the create function in the controller should work:
val productForm = Form(
tuple(
"name" -> nonEmptyText,
"category" -> nonEmptyText,
"amount" -> number,
"criticalAmount" -> number
)
)
def create = SecuredAction(IsInventoryAdmin()
).async(parse.multipartFormData) {
implicit request => {
val pr : Option[Product] = productForm.bindFromRequest().fold (
errFrm => None,
product => Some(Product(None, product._1, product._2, None, product._3,product._4))
)
request.body.file("picture").map { picture =>
pr.map { product =>
val filename = picture.filename
val contentType = picture.contentType
val filePath = s"/images/$filename"
picture.ref.moveTo(new File(filePath), replace=true)
val fullProduct = product.copy(picture = Some(filePath))
inventoryRepo.createProduct(fullProduct).map(p => Ok(Json.toJson(p)))
}.getOrElse{
Future.successful(
BadRequest(Json.obj("message" -> "Form binding error.")))
}
}.getOrElse {
Future.successful(
BadRequest(Json.obj("message" -> "File not attached.")))
}
}
}
Now my problem is the creation of a Scala Test which checks if the functionality is working. At the moment my code looks like this:
"allow inventory admins to create new products" in new RepositoryAwareContext {
new WithApplication(application) {
val token = CSRF.SignedTokenProvider.generateToken
val tempFile = TemporaryFile(new java.io.File("/images/the.file"))
val part = FilePart[TemporaryFile](key = "the.file", filename = "the.file", contentType = Some("image/jpeg"), ref = tempFile)
val formData = MultipartFormData(dataParts = Map(("name", Seq("Test Product")),("category", Seq("Test Category")),("amount", Seq("50")), ("criticalAmount", Seq("5"))), files = Seq(part), badParts = Seq(), missingFileParts = Seq())
val result = route(FakeRequest(POST, "/inventory", FakeHeaders(), formData)
.withAuthenticator[JWTAuthenticator](inventoryAdmin.loginInfo)
.withHeaders("Csrf-Token" -> token)
.withSession("csrfToken" -> token)
).get
val newInventoryResponse = result
status(newInventoryResponse) must be(OK)
//contentType(newInventoryResponse) must be(Some("application/json"))
val product = contentAsJson(newInventoryResponse).as[Product]
product.id mustNot be(None)
product.name mustBe "Test Product"
product.category mustBe "Test Category"
}
}
It would be great if anybody can help me because i can not find a solution on my own...
Kind regards!

How to populate User defined objects from list of lists in scala

I am new to Scala.
Currently trying to write a program which fetches table metadata from a database as a list of lists in the below format, and convert it to Objects of user defined type TableFieldMetadata.
The getAllTableMetaDataAsVO function does this conversion.
Can you tell me if I can write this function much better in functional way.
| **Table Name** | **FieldName** | **Data type** |
| table xxxxxx | field yyyyyy | type zzzz |
| table xxxxxx | field wwwww| type mmm|
| table qqqqqq| field nnnnnn| type zzzz |
Note: Here table name can repeat as it usually has multiple columns.
User defined classes:
1. TableFieldMetadata:
/**
* Class to hold the meta data for a table
*/
class TableFieldMetadata (name: String){
var tableName: String = name
var fieldMetaDataList: List[FieldMetaData] = List()
def add(fieldMetadata: FieldMetaData) {
fieldMetaDataList = fieldMetadata :: fieldMetaDataList
}
}
2. FieldMetaData :
/**
* Class to hold the meta data for a field
*/
class FieldMetaData (fieldName: String, fieldsDataType: String) {
var name:String = fieldName
var dataType:String = fieldsDataType
}
Function:
/**
* Function to convert list of lists to user defined objects
*/
def getAllTableMetaDataAsVO(allTableMetaData: List[List[String]]):List[TableFieldMetadata] = {
var currentTableName:String = null
var currentTable: TableFieldMetadata = null;
var tableFieldMetadataList: List[TableFieldMetadata] = List()
allTableMetaData.foreach { tableFieldMetadataItem =>
var tableName = tableFieldMetadataItem.head
if (currentTableName == null || !currentTableName.equals(tableName)) {
currentTableName = tableName
currentTable = new TableFieldMetadata(tableName)
tableFieldMetadataList = currentTable :: tableFieldMetadataList
}
if (currentTableName.equals(tableName)) {
var tableField = tableFieldMetadataItem.tail
currentTable.add(new FieldMetaData(tableField(0), tableField(1)))
}
}
return tableFieldMetadataList
}
Here is one solution. NOTE: I just used Table and Field for easy of typing into the REPL. You should use case classes.
scala> case class Field( name: String, dType : String)
defined class Field
scala> case class Table(name : String, fields : List[Field])
defined class Table
scala> val rawData = List( List("table1", "field1", "string"), List("table1", "field2", "int"), List("table2", "field1", "string") )
rawData: List[List[String]] = List(List(table1, field1, string), List(table1, field2, int), List(table2, field1, string))
scala> val grouped = rawData.groupBy(_.head)
grouped: scala.collection.immutable.Map[String,List[List[String]]] = Map(table1 -> List(List(table1, field1, string), List(table1, field2, int)), table2 -> List(List(table2, field1, string)))
scala> val result = grouped.map { case(k,v) => { val fields = for { r <- v } yield { Field( r(1), r(2) ) }; Table( k, fields ) } }
result: scala.collection.immutable.Iterable[Table] = List(Table(table1,List(Field(field1,string), Field(field2,int))), Table(table2,List(Field(field1,string))))