dimecres, 29 de gener del 2014

Scala code in Android app

I've been meeting Dani at several meetups in Barcelona lately.

We're both interested on scala but he also investigates the options to use it in android apps.

Last Saturday I remebered reading something about scala being used in android apps and tried to restore my notes to share them with Dani. Here's what I could recover:

ALERT: The following is a druid recipee based on maven.

git clone git@github.com:jayway/maven-android-plugin.git 
git clone \git@github.com:jayway/maven-android-plugin-samples.git 
cd maven-android-plugin 
mvn clean install 
cd ../maven-android-plugin-samples/ 
cd scala/ 
sed -i '' 's/2.8.0/2.10.3/' pom.xml
mvn clean install 
adb install -r  target/scala-1.0.0-SNAPSHOT.apk

Note: the previous uses a Mac OSX flavour 'sed' that requires an extra pair of simple quotes.

dissabte, 25 de gener del 2014

DI and testing without mocking in Play!

At the scala developers barcelona meetup we are running monthly challenges. This month's challenge is to implement a REST API. Easy peasy.

At some point, akustik had a question about his approach in Play! and so asked for opinions on the mailing list. Turns out I had been over the same problems few weeks earlier at my (then) current project so offered to help. Since the answer is quite reusable I'm cross-posting here so that you can comment and discuss if my suggestion is actually correct. I worked may way into the solution to make sure I remembered all steps and the PR'd my code into the challenges github: https://github.com/scala-developers-bcn/challenges/pull/29

DISCLAIMER: I'm quite new to Play! and it's very possible there's a better way than what I suggest.




Dependency Injection and testing without Mocking in Play!

Play!'s Main Problem (TM) is the abuse of singleton objects for everything. While it's a great idea to create a single instance of anything and reuse it again and again it's also a problem to make everything object (scala equivalent for classes that contain only static methods). This object-based approach makes it difficult to inject instances at will.

Back to the trigger, here's akustik's question:
I wanted to change [the controller] implementation for testing purposes without modifying the code nor changing to a variable and adding a setter. 
To which I could only reply:
You hit one of the big problems of Play! testing: there's no easy
recommendation for unit testing. The path of objects and Integration
Testing is the default suggestion. Sad.
And finally found few minutes to properly solve the problem.



Dependency Injection

To escape the object singleton mess which forbids you from doing plain old DI you first have to convert you controllers from objects to classes.

(I'm not 100% of what I'll explain now)
But once you did that you have to prepend your routes mappings with an '@' sign. That causes you HTTP requests to request an instance to Play! The responsible to resolve the required instance is a thing** called GlobalSettings.
(back to 100% sure)

Then you have to create your subclass of play.GlobalSettings and then go to application.conf and specify what your Global class is. But you class controllers still use singleton repositories. Let's make the repos injectable. Add a constructor parameter to your controller:


  class MyCtlr(repo:MyRepo) extends Controller

And now you made your controller unavailable because Play can't resolve the incoming requests. Here's where you go back to your Global class and override the method getControllerInstance so that any incoming request lets you decide what Controller to use. And there you have it!

Your Global soon becomes this:


  def flightRepo = new InMemFlightsRepository
  def flightCtlr = new FlightsCtlr(flightRepo)

  override def getControllerInstance[A](controllerClass: Class[A]): A = {
   // extend here when adding more controllers... probably a pattern matching.
    flightCtlr.asInstanceOf[A]
  }


So far so good. We got ourselves so DI wonders.



(trolling mode on)
It's at this point where your Global should be renamed ApplicationContext and you should consider your:

  def flightCtlr = new FlightsCtlr(flightRepo)

a synonim of: (blogspot won't let me use lt and gt)

  bean id=flightCtlr class=controller.FlightsCtlr scope=request
     constructor-arg="flightRepo"

You could have also done:

  val flightCtlr = ...

which would be:

  bean id=... class=... scope=singleton


Scala 1 - XML fuck you!... I mean 0

(trolling mode off)




Unit Testing (without mocking)

And so we end up on our wonderful test. 
If you've read the Play docs you probably have a test that looks like this:

    "return 200 on flights/" in {
      running(FakeApplication()) {
        val flights = route(FakeRequest(GET, "/flights")).get
         ...

Well, without you knowing it uses your Global class. The final trick to easily inject your Mock classes is to tell your Fake Application to use a different Global:
      running(FakeApplication(  withGlobal= Some(MockingGlobal() ) )) {

And that's it!
Well, no!
Oh God this is horrible!
** Remember when I said "a thing** called GlobalSettings" , well by thing I mean some bytecode that may be class or trait and I was being vague on purpose because there's both a class and a trait called
GlobalSettings and you'll need to use both to achieve DI and testing. To distinguish which GlobalSettings you are using pay close attention at the package.

  • To override Global for you app extend play.GlobalSettings
  • To inject a MockGlobal into FakeApplication when testing mixing play.api.GlobalSettigns
Putting it all together

So, to make your testing work you have to provide a MockingGlobal of yours which must mix-in play.api.GlobalSettings. I chose reusing my original Global class and just override a faked repository.

Again, while the running environment requires you to provide a subclass of play.GlobalSettings, FakeApplications expects an Option[play.api.GlobalSettings] (which is the trait). (Mother of Mercy this is wrong!)

I just go and extend and mixin to keep all my DI in a single place:

  class MyGlobal extends play.GlobalSettings
                   with play.api.GlobalSettings { ...

and finally:

  val globalForTest = new Global {
    override def flightRepo = new InMemFlightsRepository {
      override def loadAll(): List[Flight] = 

          List(Flight("ON_TIME","BOS", "CHG", "19B"))
    }
  }



Conclusion

Now, after this terrible mess lets puts this in context (no pun intended) and compare this with the 'easy' setup of a Spring-MVC app with testing and everything.
It's not much simpler but it's 100% scala so it must be cooler.

dimecres, 8 de gener del 2014

More on Neo4J 2.x: Querying over labels


I'm just starting with Neo4J and got straight into v2.0 so my first models already use labels. I just got into a case where I expected labels be of help but not sure if what I want to do is possible. Let me explain:

THE DOMAIN

Let's imagine we modelled a food chain: (in pseudo-cypher)

   (grass:Vegetable)-[:EATS]-(marie:Cow)
   (marie)-[:EATS]-(ferocious:Velociraptor)
   (marie)-[:EATS]-(joseph:Human)


In this example, 'josep' and 'ferocious' shared a great meal of 'marie'. Meanwhile poor Marie the Cow had had a last meal of grass.

DETECTING CANNIBALISM

Now, Imagine I wanted to locate cannibalism relations in my graph. It's ok for any species to eat other species but it's unacceptable to eat those of your same species. So I want to locate nodes labelled X eating other nodes also labelled X. Put another way, I'd like to write predicates over the label. So far the only option I found was replicating the label information into a property.

Turns out the solution was right in my face... that is, in the docs.

   MATCH (n)--(p)
     WHERE labels(n) = labels(p)
     RETURN n, p


Now, this works because I only added a label to each of my nodes but if I were to use labels aggressively this query would not solve my cannibalism detection.

divendres, 27 de desembre del 2013

Neo4j 2.0 - Indexing

NOTE: this post is the unexpected continuation to my yesterday's post on Neo4J. You might want to start there.

DISCLAIMER: I'm no expert on the technology and this is more of personal notes while I keep playing around and learning.



INDEXING

So I went on with Alberto's workshop slides to learn Neo4J to refresh my memory on the features until I reached a certain slide which used indexing:

     START tom=node:node_auto_index(name="Tom Hanks")  
     MATCH (tom)-[:ACTED_IN]->()<- director="" span="">
     RETURN director.name;

I then tried to execute it and found a nasty error message:
   Index `node_auto_index` does not exist 
It is clear what the problem is: the index is missing. But considering it's the auto_index I was trying to use I assume there's no more indexing magic in Neo4J. I then started a pursuit to create an index so that I could reproduce what I had in Neo4J 1.9.x. I mean, it was clear to me now that if I wanted indexing over actors-name I would have to create it myself. So I started digging google to learn some more about indexing in 2.0.0.


Creating and using Indexes

First hit I checked on Indexing is a great webinar by Michael Hunger on new features in Neo4J. For what I could gather (in the matter of indexing) is that the main difference is that they are now truly indexes meaning once created they auto-magically maintained when data is updated/added. I deduce from that statement that this wasn't the case in previous versions. BTW, the index is maintained transactionally, the index is bound to the data transactionally.

So, to create an index you simply need to:

     CREATE INDEX ON :Actor(name)

This approach really simplifies the queries so that my original Cypher query becomes:

     MATCH (actor:Actor)-[:ACTED_IN]->()<- director="" span="">
     WHERE actor.name="Tom Hanks"
     RETURN director.name;

which is simpler and also more aligned to what a SQL-John might expect. What happens under the covers is that Neo4J detects I'm filtering by a field (name) over a labelled node (actor:Actor) and then finds out there's an index by ':Actor(name)'. So, it goes and automagically tries to use it.




But it is flawed

Turns out when I tried try to create the index using:

     CREATE INDEX ON :Actor(name)

it worked at indexing nothing because my dataset doesn't use labels. So I then tried to index anything by name:

     CREATE INDEX ON :(name)
     CREATE INDEX ON :*(name)
     CREATE INDEX ON (name)

it was a total waste of time since indexing requires labels in Neo4J 2.0.x. (insert sadface here). 




INTRODUCING LABELS!

Then, back on my quest to query using an index I noticed my only chance was to create a label and have all nodes that [:ACTED_IN] another node to be labelled as Actor. Turns out to be quite straight forward:

      MATCH (actor)-[:ACTED_IN]->(movie)
      SET actor :Actor
      RETURN actor;

This finally created my label, which unblocked my power to created indexes which allowed to query using them.



FUTURE WORK

Some doubts I need to investigate further:
  • The video mentions there's "no unique indexing yet" but the video is few months old now and is based on Neo4J 2.0.0-M0
  • there's also a mention to 'simple lookups for now' and I wonder what that might mean.
  • While reading the docs on indexing I noticed it is possible to force the usage of a given index when querying (which is wonderful and also expected by some SQL-John's).
  • I read s/where it's possible to alter the indexing technology. That's definitely worth a look at.

dijous, 26 de desembre del 2013

Neo4j 2.0 - Setup and first impressions

During the Christmas Holidays I took some time to play around with Neo4J. This is not the first time I tinker with it but definitely the first time I do it unsupervised. I must say the first time I played around with Neo4J it was under @albertoperdomo 's guidance and it felt like a liberation after several years of RDBMS.

DISCLAIMER: I'm a total newbie at Neo4j so don't take my advice for anything I'll be writing, this post is more of a compendium of notes for myself to check in the future.

INSTALLING

Installing any version (I needed 2.0.0) of Neo4J is insultingly simple thanks to @thedevel script: ndm. I even tweeted about it (again, for my own reference). Let me point out that even manually, isntalling neo4j is really simple.

IMPORTING MOVIE DATABASE

During Alberto's workshop intro to Neo4J we had a lot of small quizes so that each would have to keep on investigating and putting small concepts into practice. My idea to start playing around with Neo4J was to load that clean movie database, refresh some concepts from the notes I took during the workshop and then try to move on from that point.

First issue I faced with new features in Neo4J 2.0.0 were small syntax changes causing the load of a 1.9.3 database to fail. It's ended up being something quite silly though. What used to be:

     START n=node(*) MATCH (n)-[r?]-() DELETE r,n;

now turned into:

     START n=node(*) 
     MATCH (n)--() 
     OPTIONAL MATCH ()-[r]-() 
     DELETE r,n

There seems to be 2 differences:

  • the trailing semicolon seems to be unnecessary now. It was causing a parsing error when reading the following line which caused the error message to be miss-leading since it pointed me in the wrong direction. I finally noticed the error message made no sense and tried to remove the semi-colon. It worked.
  • Second thing is the replacement of '?' char to mark 'r' relationship optional in the query. Optional matcher's syntax seems to be new (or restricted to): OPTIONAL MATCH. I then replaced the edge from the query MATCHer and created an OPTIONAL MATCHer for it. It worked but I really doubt the two queries (old 1.9.x vs new 2.0.x) do the exact same thing. What I intended was to delete everything and that's what happens, but that's not enough proof to be satisfied with the rewrite.
(I'm not sure I can freely distribute the movies.cyp database) :-(

FIRST IMPRESSIONS


  1. The web console has improved incredibly. It was a great tool already but it is now beyond awesome. You can judge yourself:
    1. not only the tabular data presentation provides a clearer view of the schemaless data,


    2. you can now peek at the results in graph view


I'm only scratching the surface of Graph DB concept at the moment. I hope I can get my hands dirty in the upcoming days...

divendres, 20 de setembre del 2013

Parallel collection manipulation in scala

Scala collections API comes packed with a very cool feature which is parallelizing any processing. See this example:

I first create a list (I could use a range or s/thing else too):

scala> List(1,2,3,4,5,6,7,8,9)
res0: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

... and then build the skeleton of my processing. What I want to to multiply each value by 1000 and then divide each value by 500:

scala> res0.map{ 
    i => i*1000
  }.map{
    i => i/500
  } 
res1: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18)

Nothing fancy so far.

Entering par

In scala every collection can be automagically wrapped into a counterpart that implements processing with a thread pool. I actually have no clue what the implementation is. Damn! I'll have to look it up. Anyway, insert 'par.' on your code and...

scala> res0.par.map{ 
    i => i*1000
  }.par.map{
    i => i/500
  }
res2: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(2, 4, 6, 8, 10, 12, 14, 16, 18)


... the list becomes a ParVector and keeps all items sorted in the original position.
Let's try and see it in action: (added random sleep to 'help' context switching)

scala> import java.util.concurrent.TimeUnitimport java.util.concurrent.TimeUnit

scala> import java.util.Random
import java.util.Random

scala> new Random

res6: java.util.Random = java.util.Random@b9d964d

scala> res0.par.map { 
    i => TimeUnit.MILLISECONDS.sleep(res6.nextInt(1000));
    println(i);
    i*1000
  }.par.map{
    i => TimeUnit.MILLISECONDS.sleep(res6.nextInt(1000));
    println(i); 
    i/500
  } 
3
7
4
5
8
2
1
9
6
7000
3000
5000
4000
1000
6000
8000
9000
2000
res13: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(2, 4, 6, 8, 10, 12, 14, 16, 18)

scala> 

Ta dah! Execution is run in parallel.

See more information re Parallel Collections on the overviews of the Scala Docs.

PS: For the curious...

If I get rid of the first 'par', the first processing is sequential, and the delays add up.


scala> res0.map { i => TimeUnit.MILLISECONDS.sleep( res6.nextInt(1000)  );println(i) ;i*1000}.par . map { i => TimeUnit.MILLISECONDS.sleep(  res6.nextInt(1000)  ); println(i); i/500 } 
1
2
3
4
5
6
7
8
9
5000
2000
1000
6000
3000
4000
9000
7000
8000
res17: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(2, 4, 6, 8, 10, 12, 14, 16, 18)