• Skip to main content
  • Skip to primary sidebar

Mark Goldenstein

  • Blog
  • Über mich
  • Impressum
Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy

scala

Tuesday, 22. April 2014 by Mark Goldenstein 9 Comments

Building a Websocket client to btcwallet using Scala and akka

I’ve been experimenting with the Bitcoin wallet daemon btcwallet for some time. btcd and btcwallet provide support for notifications via websockets which allows to process bitcoin payments in an event-driven programming style instead of polling. As of this writing proper notification support in bitcoind seems to be in limbo state (cf. this and that). It is possible to get notifications using scripts and the *notify command-line options but this seems to be a rather hackish solution.

So let’s build a websocket client to btcwallet. How do we do that in my favorite programming language, Scala?

Implementation

Usually, it’s inconvenient to use websocket or json APIs directly. As an abstraction to btcwallet’s websocket API I use akka, a library that implements the Actor model. Actors are threadless, stackless units of execution that process messages (events) serially. Messages are delivered to an Actor’s mailbox, and the Actor processes them by looping over a method that pops the first message from the mailbox.[1]David Pollak, Beginning Scala, Apress, Berkely, CA, 2009 I want to talk to btcwallet using Actor messages and receive Futures in return. Those messages will then be forwarded to btcwallet using its websocket API. When a response is available the corresponding Future will be completed.

Therefore, we can design our websocket client as follows. We define our BtcWalletActor such that it establishes a websocket connection to btcwallet as soon as it starts. If it loses the connection, it tries to reconnect in five seconds intervals. Objects that need to talk to the websocket service use the ask pattern to send requests to our actor. Finally, we define the reactions to notifications and requests by implementing the receive method of our actor.

In order to connect to our service we need a websocket library. There are several different options available. I’ve chosen Java-WebSocket because it is actively maintained, popular, and has support for TLS connections (right now only in the 1.3.1 development snapshot).

We also need a library for serializing and deserializing JSON. Again, there are numerous libraries available. I’ve chosen play-json. We also define some case classes for our actor messages, and for the JSON serialization.

Websocket messages are asynchronous, there is no request-response standard in the protocol. To work around this, btcwallet uses IDs in the request and response messages. Hence, when we make a request we need to supply and store an id for it. Then we can match the response message to our request.

To account for this aspect we implement our actor as follows. When our actor processes a message from another object that requests information from the websocket service, it creates a Promise and pipes the corresponding Future to the object that requested it. Then it generates a UUID for the request and saves it together with the Promise in a Map. After it receives the response (which also contains the UUID), it pops the Promise from the Map and fulfils it with the response. If you’re wondering what Futures and Promises are, then check out this introductory guide.

Once we put everything together, we get something like this (GitHub). I’ve provided an example in which I’m processing incoming transactions by sending the bitcoins back to the sender address. I’m using the outputs of the incoming transactions as inputs of the corresponding outgoing transactions. Therefore, there is no need to wait for confirmations.

Notes   [ + ]

1. ↑ David Pollak, Beginning Scala, Apress, Berkely, CA, 2009

Filed Under: English Tagged With: actor, akka, bitcoin, btcd, btcwallet, scala, websocket

Saturday, 5. January 2013 by Mark Goldenstein 4 Comments

Scala vs Java: weniger Code, mehr Inhalt

Scala ist eine Programmiersprache, die weitgehend unter dem Radar geblieben ist und im Unternehmensumfeld nur sehr langsam Fuß fasst.[1]im Dezember 2012 war sie nur auf Platz 34 des TIOBE Index, mit 0,32% im Vergleich zu Java auf Platz 2 mit 17,57% Zu unrecht wie ich finde, denn zum einen bietet Scala viele Möglichkeiten für einen Produktivitätsgewinn, zum anderen ist die Sprache 100%ig mit bestehenden Java Bibliotheken und Anwendungen kompatibel und läuft ebenfalls in der Java Virtual Machine (JVM).

Was sind also die wichtigsten Vorteile von Scala? Ich habe drei aus meiner Sicht herausragende Features ausgesucht, die ich im Weiteren näher beschreiben werde.

Funktionale Programmierparadigmen

Scala unterstützt alle objektorientierten Features von Java, bietet darüber hinaus aber auch viele Möglichkeiten, die sonst lediglich funktionale Programmiersprachen wie z.B. Lisp erlauben. Dies ermöglicht einen sehr prägnanten Programmierstil und führt direkt zu einer besseren Code-Verständlichkeit und -Qualität.

Experience with Scala shows that it typically takes one half to one third of the lines of code to express the same application as Java yet executes at about the same speed.[2]http://www.scala-lang.org/node/3069

Im Folgenden werde ich dieses Argument verdeutlichen. Zunächst ein Beispiel einer sogenannten for-Comprehension. For comprehensions ähneln den for loops aus Java, sind jedoch ein deutlich mächtigeres Werkzeug. So erlauben sie unter anderem, eine neue Collection durch die Iteration über eine bestehende zu erstellen (ähnlich zu den aus Python bekannten list comprehensions).[3]mehr zu dem Thema hier: http://www.scala-lang.org/node/111

Scala
1
2
3
4
// berechnet alle natürlichen Teiler einer Zahl
def factorsOf(number: Int) = for (i <- 1 to number if number % i == 0) yield i
 
factorsOf(42) // Ergebnis: Vector(1, 2, 3, 6, 7, 14, 21, 42)

Im folgenden Beispiel verwende ich eine Funktion als Filter – es werden nur diejenigen Elemente der Liste gezählt, die die übergebene Bedingung erfüllen: Ein Aufruf von factorsOf auf das Element soll einen Vector der Länge 2 zurückgeben.

Scala
1
2
3
4
5
6
// gibt die Anzahl der Primzahlen in einer Liste zurück
// Primzahlen haben exakt zwei natürliche Teiler: 1 und sich selbst
def countPrimeNumbersIn(list: List[Int]) = list.count(factorsOf(_).size == 2)
 
val range = 1 to 10 // Ergebnis: Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
countPrimeNumbersIn(range.toList) // Ergebnis: 4

Programmiere ich hingegen in Java, so würde die gleiche Logik zu folgendem Code führen:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static List<Integer> factorsOf(int number) {
  List<Integer> result = new ArrayList<Integer>();
  for (int i = 1; i <= number; i++) {
    if (number % i == 0)
      result.add(i);
  }
  return result;
}
 
public static int countPrimeNumbersIn(List<Integer> list) {
  int count = 0;
  for (int x : list) {
    if (factorsOf(x).size() == 2)
      count += 1;
  }
  return count;
}
 
public static void main(String[] args) {
  List<Integer> list = new ArrayList<Integer>();
  for (int i = 1; i <= 10; i++) {
    list.add(i);
  }
  countPrimeNumbersIn(list); // Ergebnis: 4
}

Die Methoden factorsOf und countPrimeNumbersIn, die zuvor prägnant in einer Zeile definiert waren, benötigen nun jeweils acht(!) Zeilen. In Java verschwindet die Logik also hinter Code-Bausteinen (boilerplate). Mit wachsender Code-Komplexität wächst auch der Wartungsaufwand der bereits vorhandenen Codebasis, sodass die Reduzierung von Code-Bausteinen mithilfe von Scala nicht nur die Sichtbarkeit der eigentlichen Logik erhöht, sondern auch die Software-Wartung vereinfacht und damit zu weniger Fehlern führt. Algorithmen, die mithilfe von Scalas for-comprehensions und maps programmiert wurden, lassen sich nachweislich etwa 30% schneller verstehen als solche mit Javas iterativen while-Schleifen.[4]http://www.scala-lang.org/node/3069

Scala DSLs

Nein, damit ist nicht der Breitbandanschluss gemeint, sondern DSL steht für Domain Specific Languages. Dieses Scala Feature ermöglicht es Software-Entwicklern eigene Sprachkonstrukte zu definieren, die sich nahtlos in die Programmiersprache eingliedern. Das vereinfacht die Enwicklung und verschafft auch Nicht-Programmierern die Möglichkeit, den Code zu verstehen. Im Folgenden ist ein Beispiel, wie Tests mithilfe der populären Library ScalaTest definiert werden können. Auffallend ist die sich selbst erklärende Syntax sowie die Prägnanz der Testfälle: Es sind keine Code-Bausteine nötig.

Scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class GoogleSearchSpec extends FlatSpec with ShouldMatchers with HtmlUnit {
 
  "The blog app home page" should "have the correct title" in {
    go to (host + "index.html")
    title should be ("Awesome Blog")
  }
  "The search page" should "have ten results" in {
    click on "searchbox"
    textField("searchbox").value = "Scala"
    submit()
    findAll(className("result")).size should be (10)
    capture to "search.png"
  }
}

In Java hingegen sind durch die Programmiersprache klare Grenzen gesetzt, solche Konstrukte lassen sich da nicht realisieren. Im Gegensatz zu den entsprechenden Testfällen in JUnit kommen die ScalaTest-Fälle mit deutlich weniger Code aus. Auf den direkten Vergleich mit JUnit werde ich in diesem Fall verzichten, denn dann wäre dieser Post mit Bildschirm füllenden Code-Bausteinen überladen.

Traits: Interfaces on Steroids

Oberflächlich gesehen entsprechen Scalas Traits den Interfaces aus Java; mit einem wichtigen Unterschied: Traits können Methoden nicht nur deklarieren, sondern auch bereits implementierte Methoden beinhalten.

“Das ist ja nichts Anderes als eine abstrakte Klasse!”, wird sich der mit Java erfahrene Leser nun vielleicht denken. Das stimmt so allerdings nicht. Während eine Klasse in Java lediglich von einer einzigen anderen (abstrakten) Klasse erben kann, können Klassen in Scala beliebig viele Traits einbinden. Das ist praktisch, weil dadurch die Implementierungen von mehrfach verwendeten Methoden an einem einzigen Ort (dem Trait) auftauchen, und nicht über verschiedene Klassen redundant verteilt werden müssen. Beispiel:

Scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// eine Klasse, die einen Bruch darstellt und Operatoren
// zum Vergleich mit anderen Brüchen bereitstellt
class Rational(n: Int, d: Int) {
  // numer ist der Zähler, denom der Nenner
  // ...
  def < (that: Rational) =
    this.numer * that.denom > that.numer * this.denom
  def > (that: Rational) = that < this
  def <= (that: Rational) = (this < that) || (this == that)
  def >= (that: Rational) = (this > that) || (this == that)
}
 
// Vereinfachung mithilfe des Ordered Traits: die Methoden
// "<", ">", "<=" und ">=" werden vom Trait implementiert
class Rational(n: Int, d: Int) extends Ordered[Rational] {
  // ...
  def compare(that: Rational) =
    (this.numer * that.denom) - (that.numer * this.denom)
}

In Java hingegen ist es nicht möglich in einem Interface Methoden zu implementieren.

Heute setzen bereits Twitter, Foursquare und LinkedIn auf Scala. Nach Daten von indeed.com, ist die Nachfrage nach Scala-Entwicklern seit 2010 rapide gestiegen. Es lohnt sich also diese Programmiersprache im Auge zu behalten.

Notes   [ + ]

1. ↑ im Dezember 2012 war sie nur auf Platz 34 des TIOBE Index, mit 0,32% im Vergleich zu Java auf Platz 2 mit 17,57%
2, 4. ↑ http://www.scala-lang.org/node/3069
3. ↑ mehr zu dem Thema hier: http://www.scala-lang.org/node/111

Filed Under: German Tagged With: java, jvm, scala

Primary Sidebar

Categories

  • English
  • German

Recent Posts

  • Spotify and others use an unfair formula to pay artists
  • Building a Websocket client to btcwallet using Scala and akka
  • Complex Event Processing: Language-level integration into Scala
  • 2nd Next Generation Forum Roundup
  • Präsentation 2.0 – es muss nicht immer PowerPoint sein

Recent Comments

  • Mark Goldenstein on Building a Websocket client to btcwallet using Scala and akka
  • Julio on Building a Websocket client to btcwallet using Scala and akka
  • Mark Goldenstein on Building a Websocket client to btcwallet using Scala and akka
  • Julio on Building a Websocket client to btcwallet using Scala and akka
  • Julio on Building a Websocket client to btcwallet using Scala and akka

Copyright © 2021 · Executive Pro on Genesis Framework · WordPress · Log in