Software Ramblings

Scala Java and Android

Microsoft Natural Ergonomic Keyboard 4000

| Comments

I’ve been using computers for almost 28 years now (yes, my first ever computer was ZX Spectrum when I was 3) and thoughout that time I was always using traditional keyboards. Some of them were better, some of them were worse, but I never thought about all those fancy ‘flat’, waved or ergonomic keyboards. That changed recently as I got a nice and shiny Macbook Pro.

ScalaWebSocket

| Comments

ScalaWebSocket

On April 21st I pushed the ScalaWebSocket library to GitHub. But what is it? As the name suggests, it’s WebSockets for Scala.

There are already a few implementations of WebSocket for Java, there is also the Scala project called wCS but all of them support Javaish style of passing the anonymous implementations of some kind of Listener interface. I didn’t want that as I prefer the functional style of handlers.

ScalaWebSocket is a thin wrapper around async-http-client and it exposes a more Scala-like vocabulary to interact with WebSockets.

Installation

To start using it in your project

Dependency in SBT
1
libraryDependncies += "eu.piotrbuda" %% "scalawebsocket" % "0.1.0"
Dependency in Maven
1
2
3
4
5
<dependency>
  <groupId>eu.piotrbuda</groupId>
  <artifactId>scalawebsocket_2.10</artifactId>
  <version>0.1.0</version>
</dependency>

Examples

Usage of this library is very simple.

Open a WebSocket connection
1
WebSocket().open("ws://echo.websocket.org/").sendText("text").close().shutdown()
Listen for text messages
1
2
WebSocket().open("ws://echo.websocket.org/")
.onTextMessage(msg => doSomethingWithMessage(msg))
Add several listeners
1
2
3
WebSocket().open("ws://echo.websocket.org/")
.onTextMessage(msg => doSomethingWithMessage(msg))
.onBinaryMessage(msg => doSomethingWithBinaryMessage(msg))

Future

I need this library to talk to SocketIO servers, so in version 0.2.0 I will implement some basic support for SocketIO. For now, please use it and report any issues you have. My goal for this library is to make WebSocket natural in Scala.

Trying to Deploy Scala App on OpenShift

| Comments

The beggining

This is a simple log of what I have done during past few days trying to deploy a simple app to OpenShift. I thought it would be quite easy but apparently this is beyond my knowledge. My application is a simple Hello World app. The only real requirement is that I wanted this app to compile with Scala 2.10.

Setup

I won’t discuss how to set up the application on OpenShift (unless it is really needed). The only thing worth mentioning is that you will need a Do-It-Yourself type.

SBT

There is no SBT on OpenShift. That’s right, you have to get it yourself. OpenShift however provides a nice way of storing things with its data directory (available at $OPENSHIFT_DATA_DIR) and it’s action hooks are the way to go in this case. After some trial and error this is the script I came up with.

pre_build script
1
2
3
4
5
6
7
8
9
cd $OPENSHIFT_DATA_DIR

if [[ -d sbt ]]; then
  echo "SBT installed"
else
  curl -o sbt.tgz http://scalasbt.artifactoryonline.com/scalasbt/sbt-native-packages/org/scala-sbt/sbt/0.12.2/sbt.tgz
  tar zxvf sbt.tgz sbt
  rm sbt.tgz
fi

This script basically downloads SBT from its site but only if SBT folder is not present in the data directory. Then the downloaded tgz archive gets unpacked and SBT is ready to be used.

Building

Now this is the part I spent most time with and unfortunately I can’t make it fully work :( There were several issues with building using SBT, but after some time it almost worked. Here’s the build script I developed that semi-works.

build script
1
2
3
4
5
6
7
SBT_PATH=$OPENSHIFT_DATA_DIR/sbt
SBT_DIR=$OPENSHIFT_DATA_DIR/.sbt
IVY_DIR=$OPENSHIFT_DATA_DIR/.ivy

cd $OPENSHIFT_REPO_DIR

$SBT_PATH/bin/sbt -sbt-dir $SBT_DIR -ivy $IVY_DIR start-script

This took a while to figure out. Let’s go line by line to see what everything is needed for. Lines 1, 2 and 3 define three variables that are required to run SBT (they could have been moved to pre_build script to keep everything SBT related in one place). * Line 1 simply defines the path to SBT directory. * Line 2 is a variable with path to folder SBT uses to store its data. On OpenShift you don’t have permission to write to your home directory, hence a need for custom dir. * Line 3 is like line 2 except for Ivy cache. * Line 5 then switches to the repository directory. This is the place where your sources reside and this is mostly the place where you should start your build at. * Line 7 is a simple invocation of the SBT with the predefined settings. I’m generating a start script here (using xsbt-start-script-plugin) and that’s why I only include this goal.

This somewhat works. Considering the requirements we now have a project that uses Scala 2.10. But there are now two things to consider.

At first in pre_build I downloaded SBT 0.12.2 and in project build.settings I had SBT setup to 0.12.1. This triggered a compilation of ‘compiler-interface’.

1
2
remote: [info] Compiling 1 Scala source to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes...
remote: [info] 'compiler-interface' not yet compiled for Scala 2.10.0. Compiling...

But this failed. Compilation wouldn’t finish and the process was killed. Small fix in build.properties and upping the actual SBT version to 0.12.2 fixed this – no more recompilation of ‘compiler-interface’.

When you push your project to OpenShift now, it downloads SBT, unpacks it and tries to build your project. And it fails with the same error as above.

Build fails after git push
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
remote: restart_on_add=false
remote: stop
remote: Done
remote: restart_on_add=false
remote: Running .openshift/action_hooks/pre_build
remote: pre_build
remote: SBT installed
remote: Running .openshift/action_hooks/build
remote: build
remote: /var/lib/openshift/512617424382ec272a0000b1/git/yatstaging2.git
remote: /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo
remote: [info] Loading project definition from /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/project
remote: [info] Updating {file:/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/project/}default-2353b7...
        [info] Resolving org.scala-sbt#precompiled-2_10_0;0.12.2 ...
remote: [info] Done updating.
remote: [info] Set current project to YAT Server (in build file:/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/)
remote: [info] Updating {file:/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/}default-e6271e...
remote: [info] Resolving org.scala-lang#scala-library;2.10.0 ...
remote: [info] Done updating.
remote: [debug]
remote: [debug] Initial source changes:
remote: [debug]   removed:Set()
remote: [debug]   added: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
remote: [debug]   modified: Set()
remote: [debug] Removed products: Set()
remote: [debug] Modified external sources: Set()
remote: [debug] Modified binary dependencies: Set()
remote: [debug] Initial directly invalidated sources: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
remote: [debug]
remote: [debug] Sources indirectly invalidated by:
remote: [debug]   product: Set()
remote: [debug]   binary dep: Set()
remote: [debug]   external source: Set()
remote: [debug] Initially invalidated: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
remote: [debug] Recompiling all 1 sources: invalidated sources (1) exceeded 50.0% of all sources
remote: [info] Compiling 1 Scala source to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes...
remote: [debug] Running cached compiler 18d45f0, interfacing (CompilerInterface) with Scala compiler version 2.10.0
remote: [debug] Calling Scala compiler with arguments  (CompilerInterface):
remote: [debug]   -d
remote: [debug]   /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes
remote: [debug]   -bootclasspath
remote: [debug]   /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/resources.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/rt.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jsse.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jce.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/charsets.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/netx.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/plugin.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/rhino.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jfr.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/classes:/var/lib/openshift/512617424382ec272a0000b1/app-root/data/.sbt/boot/scala-2.10.0/lib/scala-library.jar
remote: [debug]   -classpath
remote: [debug]   /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes
remote: /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/.openshift/action_hooks/build: line 21:  7042 Killed            $SBT_PATH/bin/sbt -sbt-dir $SBT_DIR -ivy $IVY_DIR start-script
remote: Running .openshift/action_hooks/deploy
remote: deploy
remote: hot_deploy_added=false
remote: start
remote: Done
remote: start: missing job name
remote: Try `start --help' for more information.
remote: Running .openshift/action_hooks/post_deploy
remote: post_deploy

The process is being killed anyway. This was driving me crazy, because no matter what I did the build always crashed. Then I tried SSH and run the script manually and… bam! It worked.

Build successful when run manually from SSH session
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
26
27
28
29
30
31
32
33
34
35
36
37
38
build
/var/lib/openshift/512617424382ec272a0000b1
/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo
[info] Loading project definition from /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/project
[info] Set current project to YAT Server (in build file:/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/)
[debug]
[debug] Initial source changes:
[debug]   removed:Set()
[debug]   added: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug]   modified: Set()
[debug] Removed products: Set()
[debug] Modified external sources: Set()
[debug] Modified binary dependencies: Set()
[debug] Initial directly invalidated sources: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug]
[debug] Sources indirectly invalidated by:
[debug]   product: Set()
[debug]   binary dep: Set()
[debug]   external source: Set()
[debug] Initially invalidated: Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug] Recompiling all 1 sources: invalidated sources (1) exceeded 50.0% of all sources
[info] Compiling 1 Scala source to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes...
[debug] Running cached compiler 12a6774, interfacing (CompilerInterface) with Scala compiler version 2.10.0
[debug] Calling Scala compiler with arguments  (CompilerInterface):
[debug]   -d
[debug]   /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes
[debug]   -bootclasspath
[debug]   /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/resources.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/rt.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jsse.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jce.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/charsets.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/netx.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/plugin.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/rhino.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/lib/jfr.jar:/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.9/jre/classes:/var/lib/openshift/512617424382ec272a0000b1/app-root/data/.sbt/boot/scala-2.10.0/lib/scala-library.jar
[debug]   -classpath
[debug]   /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/scala-2.10/classes
[debug] Scala compilation took 34.206682197 s
[debug] Step 2 changed sources and immdediate dependencies:
[debug]   Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[debug] Non-trivial strongly connected components:
[debug]
[debug] Step 2 invalidated sources:
[debug]   Set(/var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/src/main/scala/pl/apptile/yat/YAT.scala)
[info] Wrote start script for mainClass := Some(pl.apptile.yat.YAT) to /var/lib/openshift/512617424382ec272a0000b1/app-root/runtime/repo/target/start

This is quite puzzling and I can’t figure out why automatic build doesn’t work. What’s worth mentioning though is that it does work when you change Scala to 2.9.2. But it’s against requirements and hence I stopped at this point, unable to continue.

Summary

While I was really happy that most of the things were quite easy to start with, inability to compile the sources makes it a no-no for further work, like actually starting a spray-can server. My application was a Hello World app and if this can’t compile… Sorry OpenShift, for now I’m switching to CloudFoundry to see how it fares.

Angular Directive for Password Matching

| Comments

Recently at Bootstrap I was working on the profile page part. I had to introduce a simple validation of passwords – when you type in your password, you often have to repeat it. This was implemented in a few places already, however it wasn’t correct – changing the original password did not trigger validation.

To see how this works, just go to the Bootstrap page and play with the registration form’s “password” and “repeat password” inputs. All code snippets are taken from Bootstrap.

Requirements

We have two input fields and we just need to validate whether values in them are synchronized. Values entered in both these fields need to be the same, if they’re not, then display error message next to the second input field that the contents are invalid.

Simple approach

When I started, there was something implemented already. It was a simple solution that based on the ng-change directive. This directive was attached to the repeated field and every time the value changed, method checkPassword() in RegisterController was called.

How checkPassword() was used
1
<input type="password" name="repeatPassword" id="repeatPassword" placeholder="repeat password" ng-model="user.repeatPassword" ng-change="checkPassword()" required>
Validation in checkPassword method
1
2
3
$scope.checkPassword = function () {
    $scope.registerForm.repeatPassword.$error.dontMatch = $scope.user.password !== $scope.user.repeatPassword;
};

The dontMatch error flag was then used to display error message.

Using dontMatch flag to display error
1
<span class="text-error" ng-show="registerForm.repeatPassword.$dirty && registerForm.repeatPassword.$error.dontMatch">Passwords don't match!</span>

This isn’t the best solution. First of all, this only checked equity upon changing the repeated field, not the original password field. To make this work it would be required in both original and repeated fields. This also wasn’t reusable – to use it in another place, checkPassword method had to be actually copied.

Angular directive to the rescue

Directives in AngularJS are used to create reusable components so I thought about how to use them to solve the validation problem. It was rather easy and straightforward.

The repeatPassword directive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
directives.directive("repeatPassword", function() {
    return {
        require: "ngModel",
        link: function(scope, elem, attrs, ctrl) {
            var otherInput = elem.inheritedData("$formController")[attrs.repeatPassword];

            ctrl.$parsers.push(function(value) {
                if(value === otherInput.$viewValue) {
                    ctrl.$setValidity("repeat", true);
                    return value;
                }
                ctrl.$setValidity("repeat", false);
            });

            otherInput.$parsers.push(function(value) {
                ctrl.$setValidity("repeat", value === ctrl.$viewValue);
                return value;
            });
        }
    };
});
Using repeatPassword directive
1
<input type="password" name="repeatPassword" id="repeatPassword" placeholder="repeat password" ng-model="user.repeatPassword" repeat-password="password" required>

At first I was trying to attach $parser function to just the element the directive was attached to. But this didn’t work, because when I was comparing to the value stored in controller the results not always were correct. The reason for this is that invalid values are not passed to controller, and so when one value was invalid, it wasn’t present in controller, and directive failed. As you can see, the trick is to attach $parsers to each control that requires syncing. This took me some time to figure out, but for now it works quite nice.

Summary

Angular directives are quite nice. They can be used to create reusable components and in this case, I created something that was automatically usable in three places, without the need to writing any controller code. Moreover, this directive is not only for passwords – rename that to stringsMatch and you get a nice directive that checks if you string values are in sync. Neat!

This change has been introduced in Bootstrap in this commit.

My First Month at SoftwareMill

| Comments

The year 2012 was a year of change to me. First I was moved to a new team in CGM Poland. Things were nice at first, but after a while I lost all my motivation to work. It was time to change the organization and so I applied to a company called SoftwareMill. Why them? Trully a coincidence. I was browsing some stuff on LinkedIn and I stumbled upon their job posting and I got intrigued by the fact that they mentioned possibility to work from home. As it turned out, the whole team is distributed! But then I took a closer look at the company and noticed that on SoftwareMill website there’s a section about developers. Browsing short descriptions of those who worked there I thought that it was a very good company to work at. So I applied in August. It took a longer while to finish the recruitment process (I wasn’t accepted at first), but I finally started work at SoftwareMill on 2nd January 2013.

Now a month has passed and I have to say that I’m very happy I was given the chance. Not only have I met some brilliant people but it was also a great cultural change for me: from big company, corporation, to a smaller entity with more focus on single developers.

This experience is quite pleasant. Frequent code reviews is something I often missed in my previous jobs but here I have them almost every push to Git repo. That’s reassuring, as any mistake I make may be quickly recognized by someone else, but I think I don’t have to stress out how important code reviews are :)

The next thing I’d like to mention is the Scrum/Chrum meetings. Every team has a Scrum sometime before 10:00. It’s your normal Scrum meeting where you answer the three questions. Then is the Chrum meeting. Since the team is distributed, we don’t see each other normally, so at 10:00 we have a video meeting where we answer additional, fourth question. This question can be anything – from what was your yesterday’s dinner to how does your surrounding look like at the moment. This is really quite fun meeting and most importantly it’s self organizing. There is no specific order at which people speak out but we usually end the meeting around 10:20. When the official meeting is over we are free to discuss about anything.

Working from home was something I always wanted to try and now I have the chance. I was affraid though that some responsibilities might take over my work (like cooking dinner, for example) but fortunately that’s not the case. I think I adapted pretty quickly to working from home, despite many distractions. There are occasional problems, like having a sick kid at home, but other than that, distractions can be avoided. It’s also worth noting that remote work does not equal to working from home, which I hope to prove sometime soon :)

For now I’m developing this open source project called SML Bootstrap and while it’s nothing too big, it helps me to familiarize with how things work at SoftwareMill. I also encourage you to check this project out – it’s quite simple, but can be useful if you start your project with Scala and AngularJS.

As a last note I’ll just mention that I was given this Macbook Pro to work with ;) While I never agreed with how Apple works, but I have to admit that the quality of build of this machine is just superb.

Scala and Android: AsyncTask Implementation Problem

| Comments

So I recently started some really simple Scala development for Android. However because I’m a very lucky person, I stumbled upon my first problem the very first moment I tried doing something nice.

There is a neat way for doing things in Android with AsyncTasks – this cool utility abstracts away the need for creation and management of threads for invoking stuff that would block UI thread. For more info just go to AsyncTask documentation.

So I tried doing something with this cool AsyncTask and here’s the class definition:

1
2
3
4
5
6
class ObtainRequestTokenTask() extends AsyncTask[String, Void, String] {
...
override protected def doInBackground(p1: String*): String = {
...
}
}

The major problem here is that this thing compiles. Running this on Android emulator I got an exception suggesting that doInBackground is not implemented (it’s abstract in AsyncTask)… So where’s the problem?

Googling about this I found this bug. I won’t go into detail, however to make this code work you have to actually change the signature of doInBackground. Instead of String input, you need AnyRef and just cast params to the desired class.

For me this now looks something like this:

1
2
3
4
5
6
7
class ObtainRequestTokenTask() extends AsyncTask[AnyRef, Void, String] {
...
override protected def doInBackground(p1: AnyRef*): String = {
p1.head.asInstanceOf[String]
...
}
}

Warsjawa 2012

| Comments

I didn’t attent any conference for the past 18 months. Last time I was on one was when I was sent to eye-opening meeting with Greg Young. Recently a friend of mine suggested that we should go to Warsjawa 2012 conference as it’s free and relatively close to Lublin.

We decided to sign up for a workshop called ‘One day with a difficult client’ that was lead by guys from SoftwareMill. The idea of the workshop was to show attendees some common problems people face when working with their clients. Even though I don’t work directly with our client every day I read a few things here and there how they can be PITA and I had some expectations regarding this workshop. It turned out great and here’s how it went.

The whole workshop began with a short, but fun, game which helped every attendee remember other’s names. This game is very simple: just say your name and make up some kind of symbol (V sign, finger on your mouth, anything) and the person after you has to repeat EVERY name and EVERY symbol before. There were 13 attendees and 3 leaders so after 16 rounds we pretty much knew every name. Very fun way of introducing a group of people to each other, and very efficient at that.

After that we were split into three groups and each group was given a contract to build a space capsule. We were presented with some stuff that we could use (scissors, paper, glue, boxes, foil – you get the picture) and we had some time to think about the contract. The whole game was to take around 1,5 hours and it was split into a few 15-20 minute sprints. After each sprint our client would come and look at what we’ve done and answer questions.

When the time run out we were taken to the launch site – the capsule had to actually fly! The clients were mostly happy and we mostly delivered what they wanted. Or did we? That was the whole point of the workshop. We started out with a contract for a space capsule and ended up with a prototype model that instead of flying out to space was to fly just three meters straight from the launcher, which wasn’t a rocket booster but a simple slingshot.

At the end, we were doing retrospectives in teams and shared our experiences with others. Some teams had problems other didn’t and guys from SoftwareMill told us what we did good and where our attention should be next time. I can’t tell for other teams, but our team didn’t have most of the problems, and we also did the best looking capsule! Unfortunately we did one thing wrong – we emphasized one aspect of the capsule without much regard to another which resulted in the best looking and most secure capsule that… didn’t fly.

There were a few things I didn’t like though. The difficult client didn’t appear that difficult after all. I expected the client to be a little more aggresive, inconsistent (the ‘client’ had three representatives and on each meeting another representative was present, and mostly agreed with his/her colegues) and impatient. But apparently some previous groups had problems already and this workshop was meant to be fun and not hardcore :) I can live with that.

Another ‘thing’ was that shortly after the workshop was over, everyone was gone. We couldn’t talk more about what happened and share more experiences, not only regarding workshops. I’d definately fix that next time because for me this was the worst thing to happen.

Overall, it was one of the best days lately. Lots of laughter, lots of good experience and lots of great people to work with. I think I will attend Warsjawa 2013 :)

Scala Case Classes and Annotations, Part 2

| Comments

Before proceeding please remember that I’m learning Scala and what follows is the result of lack of proper knowledge :)

In the previous article I wrote how to specify where annotations should be applied. But if you remember an example class I ported from Java to Scala there was one thing left to do and that was using constants in annotations.

In Java you can easily do

1
2
3
4
public static final String USER_ID = "userId";

@Field(USER_ID)
private long userId;

but in Scala this doesn’t work.

First of all I tried adding constant in a class like this:

1
2
3
4
5
case class ScanningBookmark(@(Field@field)(USER_ID) userId: Long,
                            @(Field@field)(STATUS_ID) statusId: Long) {
    final val USER_ID:String = "userId"
    final val STATUS_ID:String = "statusId"
}

but in Scala USER_ID and STATUS_ID are not resolved. Since normally an object is used for defining static content I then tried using a companion object to store those constants:

1
2
3
4
5
6
case class ScanningBookmark(@(Field@field)(ScanningBookmark.USER_ID) userId: Long,
                            @(Field@field)(ScanningBookmark.STATUS_ID) statusId: Long)
object ScanningBookmark {
    final val USER_ID:String = "userId"
    final val STATUS_ID:String = "statusId"
}

but this also didn’t work as it gave the following error:

1
2
error: annotation argument needs to be a constant; found: ScanningBookmark.USER_ID
case class ScanningBookmark(@(Field@field)(ScanningBookmark.USER_ID) userId: Long,

At this point I gave up. I tried looking for answer at Google but didn’t find it – or as it occured later – just missed it.

The problem here is that in Scala a constant doesn’t have type in definition. The last thing necessary to make those constants work was removing the String type from definitions:

1
2
3
4
5
6
case class ScanningBookmark(@(Field@field)(ScanningBookmark.USER_ID) userId: Long,
                            @(Field@field)(ScanningBookmark.STATUS_ID) statusId: Long)
object ScanningBookmark {
    final val USER_ID = "userId"
    final val STATUS_ID = "statusId"
}

Now it compiles and works as expected.

This is the end of my short experience with Scala and annotations.

Scala Case Classes and Annotations, Part 1

| Comments

Recently in Twittory I moved from Java to Scala. Well, to be honest I just switched from Java to Scala syntax and will move on to adapt to functional programming principles.

There was one glitch during the process. I am using Spring Data for MongoDb and to ease up a few queries I used statics to define field names of objects I store.

Here’s an example: very simple class that I use to store tweet scanning bookmarks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ScanningBookmark {
    public static final String USER_ID = "userId";

    public static final String STATUS_ID = "statusId";

    private ScanningBookmark(long userId, long statusId) {
        this.userId = userId;
        this.statusId = statusId;
    }

    @Field(USER_ID)
    private long userId;

    public long getUserId() {
        return userId;
    }

    @Field(STATUS_ID)
    private long statusId;

    public long getStatusId() {
        return statusId;
    }
}

Storing this thing with Spring Data. The static fields defining field names are here so that somewhere else I can define a query using those fields. The @Field annotations allow customization of field names in collections and while here they are the same as actual field names, they could be set differently.

Now when I was rewriting this to Scala, it’s quite obvious I ended up with a case class.

1
case class ScanningBookmark(userId: Long, statusId: Long)

But the problem with case class is that adding @Field annotations doesn’t work anymore. This is because writing like this:

1
2
case class ScanningBookmark(@Field("userId") userId: Long,
                            @Field("statusId") statusId: Long)

places the @Field annotation on constructor arguments, fields and Scala accessors which probably makes Spring Data scanner fail. The result is that these fields are no longer customizable and I wanted to somehow remedy that.

Playing with @BeanProperty annotation didn’t solve the problem because apparently the @Field annotation is then also placed on generated accessors. But solution to this problem is actually quite easy. In Scala there are target meta-annotations that can be put on the annotation type when instantiating the annotation. There are six of those: @beanGetter, @beanSetter, @field, @getter, @setter, @param. Consult the target package for more info.

The solution? It’s very simple:

1
2
case class ScanningBookmark(@(Field@field)("userId2") userId: Long,
                            @(Field@field)("statusId2") statusId: Long)

And that’s it! But there’s one last thing to make it behave like Java version. In Java I used statics to define field values (so that there’s no problem when some name changes). So I want something like this:

1
2
3
4
5
case class ScanningBookmark(@(Field@field)(USER_ID) userId: Long,
                            @(Field@field)(STATUS_ID) statusId: Long) {
  final val USER_ID: String = "userId2"
  final val STATUS_ID: String = "statusId2"
}

But this is not how things work in Scala and it took a while to learn that :) But this is for another short post.

Function Programming Principles in Scala Course - Week One

| Comments

So the course started a week ago and I’d like to share my opinion after the first week.

First of all I got this feeling that most people attending the course thought that it’ll be a Scala course. While Scala is used to demonstrate functional programming principles it is not a Scala course. You have to know Scala on your own, however for now Martin Odersky does explain it’s syntax. If you’re into learning Scala only, this is not a course for you IMO.

Lectures are recorded with good quality and Martin’s English is very good, he also speaks slowly. This is OK for people who have problems with understanding English and for those who don’t, you can increase video speed to 1.25x or even 1.5x and it’s still quite easy to understand what he’s saying.

Since it’s my first Coursera course, I was surprised with the first quiz during a lecture :) but these are nice little stops for you to think. Sometimes you have to check a proper answer and sometimes you are only asked to do something on your own.

As for assignments, they are pretty clear. You have to do a thing or two and submit your solutions. Altough there are tests written for you already, the very first thing that I did for the first assignment was adding a few tests for corner cases. Later on things were smoothly as the assignments were not that hard.

I’ve had a few problems with the countChange function but mainly because I made some wrong assumptions (thanks go to @marcinderylo for pointing that out to me). I didn’t use Eclipse or Intellij Idea for the first assignment – I used vim and just set tests to run continously in sbt. For the next week I plan to use Intellij, however the course is setup using Eclipse (it’s probably easier to do, since Scala plugin for Intellij is like alpha stage).

And that’s it. This is the first ‘real’ learning since I finished university, but this time it’s for the good cause :) I hope everyone enjoys the course and I really hope that my skills in functional programming will benefit from the it.