'initialize' called before #FXML variables bound - scala

In my Scala application, I load the FXML file in the constructor of the controller and set the controller with fxmlLoader.setController(this).
UPDATE (1): A more comprehensive example:
abstract class Controller[A <: Parent] {
val root: A = loadRoot()
private val stage: Stage = new Stage()
def openWindow(): Unit = {
stage.setScene(new Scene(root))
stage.show()
stage.toFront()
}
private def loadRoot(): A = {
val loader = new FXMLLoader(getDefaultLocation())
loader.setController(this)
loader.load()
}
def getDefaultLocation(): URL = ???
}
--
class SampleController private() extends Controller[VBox] {
#FXML private var text: TextField = _
#FXML def initialize(): Unit = {
text.textProperty().set("That is some text.")
}
}
object SampleController {
def apply(): SampleController = new SampleController()
}
UPDATE (2): SampleController() is called whithin an Akka actor:
val controller = SampleController()
Platform.runLater(() => controller.openWindow())
I now experience that sometimes the initialize method is called before the c variables are bound. Can anyone think of any circumstances when that can happen?

Related

Is there any way to rewrite the below code using Scala value class or other concept?

I need to write two functions to get the output format and the output index for file conversion. As part of this, I wrote a TransformSettings class for these methods and set the default value. And in the transformer class, I created a new object of TransformSettings class to get the default values for each job run. Also, I have another class called ParquetTransformer that extends Transformer where I want to change these default values. So I implemented like below.
class TransformSettings{
def getOuputFormat: String = {
"orc"
}
def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("orc.column.index.access")
}
}
class Transformer{
def getTransformSettings: TransformSettings = {
new TransformSettings
}
def posttransform(table: AWSGlueDDL.Table):Dateframe ={
val indexAccess = getTransformSettings.getOuputIndex(table: AWSGlueDDL.Table)
........
}
}
class ParquetTransformer extends Transformer{
override def getTransformSettings: TransformSettings = {
val transformSettings = new TransformSettings {
override def getOuputFormat: String = {
"parquet"
}
override def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("parquet.column.index.access")
}
}
}
}
Is there a way to avoid creating a brand new object of TransformSettings in Transfomer class every time this is called?
Also is there a way to rewrite the code using Scala value class?
As #Dima proposed in the comments try to make TransformSettings a field / constructor parameter (a val) in the class Transformer and instantiate them outside
class TransformSettings{
def getOuputFormat: String = {
"orc"
}
def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("orc.column.index.access")
}
}
class Transformer(val transformSettings: TransformSettings) {
def posttransform(table: AWSGlueDDL.Table): DataFrame ={
val indexAccess = transformSettings.getOuputIndex(table: AWSGlueDDL.Table)
???
}
}
val parquetTransformSettings = new TransformSettings {
override def getOuputFormat: String = {
"parquet"
}
override def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("parquet.column.index.access")
}
}
class ParquetTransformer extends Transformer(parquetTransformSettings)
You don't seem to need value classes (... extends AnyVal) now. They are more about unboxing, not about life-cycle management. TransformSettings and Transformer can't be value classes because they are not final (you're extending them in class ParquetTransformer extends Transformer... and new TransformSettings { ... }). By the way, value classes have many limatations
https://failex.blogspot.com/2017/04/the-high-cost-of-anyval-subclasses.html
https://github.com/scala/bug/issues/12271
Besides value classes, there are scala-newtype library in Scala 2 and opaque types in Scala 3.

Close open resource in Scala which does not extend Autocloseable

I am trying to determine a good way to close opened resource. I am using Micrometer and some resources (all coming from micrometer) that I have added in the binderList extends AutoCloseable and overrides close method but few of them do not.
https://mvnrepository.com/artifact/io.micrometer
class MetricConfiguration extends AutoCloseable{
var binderList : List[MeterBinder]
def initializePrometheusMetricsConfiguration(): Unit = {
binderList = List (
new JvmGcMetrics(),
new JvmHeapPressureMetrics(),
new JvmMemoryMetrics()
)
init(binderList)
}
private def init(binders: List[MeterBinder]): Unit = {
Metrics.globalRegistry.config().
meterFilter(new MeterFilter {
override def map(id: Meter.Id): Meter.Id = {
id.withName("hello" + id.getName)
}
})
binders.foreach(b => b.bindTo(Metrics.globalRegistry))
}
}
override def close(): Unit = ???
I am new to scala, I know I would have done in Java by extending Closeable and implementing the method
#Override
public void close() {
this.binderList.stream()
.filter(b -> b instanceof AutoCloseable)
.map(b -> (AutoCloseable) b)
.forEach(Closeables::closeQuietly);
}
Your Java close method translates nicely to Scala:
binderList
.collect { case b: AutoCloseable => b }
.foreach(Closeables.closeQuietly)

How do you test the read-side processor in Lagom?

I have a read-side that is supposed to write entries to Cassandra, I would like to write a test that ensure that sends an event to the read-side and then check in Cassandra that the row has indeed been written. How am I supposed to access a Cassandra session within the test?
I do it following way:
class MyProcessorSpec extends AsyncWordSpec with BeforeAndAfterAll with Matchers {
private val server = ServiceTest.startServer(ServiceTest.defaultSetup.withCassandra(true)) { ctx =>
new MyApplication(ctx) {
override def serviceLocator = NoServiceLocator
override lazy val readSide: ReadSideTestDriver = new ReadSideTestDriver
}
}
override def afterAll(): Unit = server.stop()
private val testDriver = server.application.readSide
private val repository = server.application.repo
private val offset = new AtomicInteger()
"The event processor" should {
"create an entity" in {
for {
_ <- feed(createdEvent.id, createdEvent)
entity <- repository.getEntityIdByKey(createdEvent.keys.head)
entities <- repository.getAllEntities
} yield {
entity should be(Some(createdEvent.id))
entities.length should be(1)
}
}
}
private def feed(id: MyId, event: MyEvent): Future[Done] = {
testDriver.feed(id.underlying, event, Sequence(offset.getAndIncrement))
}
}

Scala - How to call inner class method?

I have in one scala file following class (and bellow main method):
class OuterClass {
class Inner {
def innerMethod(): Unit = {
println("innerMethod")
}
class InnerMost {
innerMethod()
}
}
}
Now want to call that class from main method:
object main {
def main (args: Array[String] ): Unit = {
println("Main")
val pt = new OuterClass
...
}
}
How to achieve that?
To instantiate the nested class Inner and then InnerMost
val pti = new pt.Inner
val ptim = new pti.InnerMost

Scala closure context

I am not a Groovy expert, but I did read the book "Groovy in Action". In Groovy, each closure comes with a "context", where the items inside the closure can get access to pseudo-variables like "this", "owner", and "delegate", that let the items know who called the closure. This allows one to write DSLs like this (from Groovy in Action):
swing = new SwingBuilder()
frame = swing.frame(title:'Demo') {
menuBar {
menu('File') {
menuItem 'New'
menuItem 'Open'
}
}
panel {
// ...
}
}
Note that 'menuBar' "knows" that it belongs to 'frame' because it can get context information about the owner and delegate of the closure.
Is this possible to do in Scala? If so, how?
One way is to use a scala.util.DynamicVariable to track the context. Something like the SwingBuilder could be implemented as
import scala.util.DynamicVariable
import javax.swing._
object SwingBuilder {
case class Context(frame: Option[JFrame], parent: Option[JComponent])
}
class SwingBuilder {
import SwingBuilder._
val context = new DynamicVariable[Context](Context(None,None))
def frame(title: String)(f: =>Unit) = {
val res = new JFrame(title)
res.add(new JPanel())
context.withValue(Context(Some(res),context.value.parent)){f;res}
}
def menuBar(f: =>Unit) = {
val mb = new JMenuBar()
context.value.frame.foreach(_.setJMenuBar(mb))
context.withValue(Context(context.value.frame,Some(mb))){f;mb}
}
def menu(title: String)(f: =>Unit) = {
val m = new JMenu(title)
context.value.parent.foreach(_.asInstanceOf[JMenuBar].add(m))
context.withValue(Context(context.value.frame,Some(m))){f;m}
}
def menuItem(title: String) = {
val mi = new JMenuItem(title)
context.value.parent.foreach(_.asInstanceOf[JMenu].add(mi))
}
}
object Test {
def main(args: Array[String]) {
val builder = new SwingBuilder()
import builder._
val f = frame("Demo") {
val mb = menuBar {
menu("File") {
menuItem("New")
menuItem("Open")
}
}
}
f.setVisible(true)
}
}