Friday, November 18, 2011

How to create public Maven repository for free

I needed QuickFixJ 1.5.1 to be available for Maven dependency resolution. Official QuickFixJ repository doesn't contain the latest version of the projects artifacts. In order to allow the other people to build my QuickFixJ 1.5.1 related project I needed to put QuickFixJ libraries in Maven repository available via the Internet.

So I created my "private public" repository on the Google Code Project SVN server. This is approach I know from the Apache Camel extra project where we put missing dependencies from the 3rd parties this way. This is possible since Google Projects allows you to display the SVN repository of your project via the web browser. Useful and free of charge :) .

Saturday, November 12, 2011

Scala resources summary

This is the summary post to keep my favorite Scala-related resources and references in one place.

Books
  • Beginning Scala by David Pollack, 1st edition, Packt publishing
  • Scala tutorial at Stack Overflow

    Forums
  • Scala tag at Stack Overflow (plus RSS channel for it)
  • Wednesday, November 9, 2011

    Transformation Channel pattern for Scala

    I'm particularly keen in Scala because of my strong integration background. Scala (and functional programming in general) promotes message-based communication between the objects. When we design the applications to be more message-oriented, we also could start using patterns typical for integration architecture (like Hohpe's EIP patterns).

    One of the most powerful integration pattern is Message Translation (aka Message Transformation). The idea behind this pattern is quite simple. You intercept the message and affect it in some way.



    How this pattern can apply to the Object Oriented design? Imagine that you want to pass some data from one object (let's call it Data Provider) to the another that will perform some operation on the data (we will refer the second object as Data Receiver). Then Data Receiver processes the data and returns it.



    We may also want Data Receiver to send processed data to some other object.



    The processing scheme presented above is quite common. The idea behind Message Transformation pattern in the context of Object Oriented design is to allow us to intercept the latter processing scheme in order to affect the message sent between Data Provider and Data Receiver.

    To achieve the goal described above, we need to add a layer of abstraction between the communication objects. Let's name it TransformationChannel. Instead of sending messages directly to Data Receiver, Data Provider will send messages to the channel. Than channel will notify the Data Receiver that message with data is available to be processed.



    Channel allows us to register message translators to listen for the data and modify it before Data Receiver gets it.



    Using the Message Translator pattern and Transformation Channel we can easily add additional behavior to the default version of the algorithm processing our data.

    I've created a simple implementation of the Transformation Channel in Scala. It uses partial functions and pattern patching as Message Translators. In the example below Strings sent to the Transformation Channel are converted to uppercase by Data Receiver. This base functionality can be packed into the jar file and delivered to the other team of developers.

    // Some data to process
    val data = "foo"
    
    // Data Receiver which converts Strings to upper case
    val dataReceiver: PartialFunction[Object, String] = {
      case s: String => s.toUpperCase
    }
    
    // Transformation channel with registered Data Receiver 
    val channel = new TransformationChannel(dataReceiver)
    
    // Data processing
    val upperCasedData: String = channel.transform(data)
    


    If at some point the other team of developers decides that data should be affected somehow before the processing, they can dynamically add Message Translator (defined as partial function) to the channel defined by us.

    // Register Message Translator
    channel.addPreTransformation {
       case s: String => "prefix_" + s
     }
    
    // Process data
    val prefixedAndUpperCasedData: String = channel.transform(data)
    
    When would you like to use Transformation Channel?
    • when you want to deliver default implementation of data exchange between two objects but still be able to dynamically modify or extend this behavior
    • when you can't predict all possible scenarios of data exchange between two objects
    • when data exchanged between two object is likely to be modified by other collabolators
    • when you want to provide plug-in point for communication between two objects
    • when you want to provide unifed implementation of the Observer design pattern
    • when you want achieve very loose coupling between two communicating objects

    Friday, October 28, 2011

    Using Dropbox to share Ubuntu desktop state between multiple machines

    I like to have my desktop shared between multiple Ubuntu machines so that I can just log in the another computer and continue to work on my "stuff". Shared desktop is also useful if you need to reinstall one of your Ubuntu box instantly (for example because of the broken version update) and do not want to lose the state of your desktop.

    The trick is simply to remove your original desktop directory and to create the symbolic link to the directory in your Dropbox folder instead.
    hekonsek@Drone:~$ rm -r ~/Desktop
    hekonsek@Drone:~$ ln -s ~/Dropbox/Desktop ~/Desktop
    Now all changes to your desktop state will be synchronized with the Dropbox account. Apply this configuration trick to all your machines and you got desktop synchronized between multiple Ubuntu instances. Plus desktop backup for free :) .

    Wednesday, October 26, 2011

    Passing Java arrays to Scala classes - generics compatibility issue

    Imagine that you got a library class written in Scala (2.8.0). The class holds an array of Strings.
    class LibraryClass(array : Array[String]) {
    
      override def toString = "Array size: " + array.length.toString
    
    }
    
    Now you want to instantiate this class from Scala code:
    object ScalaClient extends Application {
      var libraryClass = new LibraryClass(Array[String]("foo"))
      println(libraryClass)
    }
    
    You can do the same from Java code:
    public class JavaClient {
    
      public static void main(String[] args) {
        LibraryClass libraryClass = new LibraryClass(new String[]{"foo"});
          System.out.println(libraryClass);
      }
    
    }
    
    No problems. Everything compiles and runs smoothly.

    Now modify the LibraryClass to be parametrized:
    class LibraryClass[T](array : Array[T]) {
    
      override def toString = "Array size: " + array.length.toString
    
    }
    
    Try to run it from Scala code:
    object ScalaClient extends Application {
      var libraryClass = new LibraryClass(Array[String]("foo"))
      println(libraryClass)
    }
    
    That works fine. Now try to call the parametrized version of LibraryClass from Java code:
    public class JavaClient {
    
      public static void main(String[] args) {
        LibraryClass<String> libraryClass = new LibraryClass<String>(new String[]{"foo"});
          System.out.println(libraryClass);
    }
    
    }
    
    Exception in thread "main" java.lang.NoSuchMethodError: LibraryClass.<init>([Ljava/lang/Object;)V
     at JavaClient.main(JavaClient.java:6)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:601)
     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
    
    Yes, we've just created the code that is runnable under Scala but fails if called from Java. To make our LibraryClass compatible with both Scala and Java clients we need to narrow its parameter type definition to classes extending from the java.lang.Object:
    class LibraryClass[T<:Object](array : Array[T]) {
    
      override def toString = "Array size: " + array.length.toString
    
    }
    
    Tip of a day - if you intend to use your Scala classes from Java code declarate their type parameters as [T<:Object] instead of [T].

    Wednesday, October 19, 2011

    Android resources summary

    This is the summary of Android resources I find particularly useful.

    Books
    • Hello, Android (3th edition) by Ed Burnette, Pragmatic bookshelf, 2010

    Tools documentation

    Friday, October 14, 2011

    Starting up the Android project with android-maven plug-in


    For some people (like me) all software projects must be Mavenized. Android projects are no exception from this rule.


    The motivation behind using Maven with Android is:
    • dependency management 
    • smooth integration with Maven lifecycle
    • support for exisitng tools (Continious Integration, ProGuard obfuscator, Check Style, Find Bugs, JDepend, etc) via Maven plug-ins system
    I decided to try out android-maven plug-in since it is recommended by the Sonatype.

    At first I created the Android project from the archetype...

    mvn archetype:generate \
      -DarchetypeArtifactId=android-quickstart \
      -DarchetypeGroupId=de.akquinet.android.archetypes \
      -DarchetypeVersion=1.0.6 \
      -DgroupId=helloCompany \
      -DartifactId=helloAndroid
    

    ...and then built it...

    hekonsek@Drone:~$ cd tmp/helloAndroid
    hekonsek@Drone:~/tmp/helloAndroid$ mvn clean install
    ...
    [INFO] Installing /home/hekonsek/tmp/helloAndroid/target/helloAndroid-1.0-SNAPSHOT.apk to /home/hekonsek/.m2/repository/helloCompany/helloAndroid/1.0-SNAPSHOT/helloAndroid-1.0-SNAPSHOT.apk
    [INFO] Installing /home/hekonsek/tmp/helloAndroid/target/helloAndroid-1.0-SNAPSHOT.jar to /home/hekonsek/.m2/repository/helloCompany/helloAndroid/1.0-SNAPSHOT/helloAndroid-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 13 seconds
    [INFO] Finished at: Wed Oct 12 20:47:26 CEST 2011
    [INFO] Final Memory: 42M/493M
    [INFO] ------------------------------------------------------------------------
    

    At first glance everything went fine so we expect to have Android APK artefact packaged and ready to be deployed to the device. However when I try to do the latter I get the following error message:

    hekonsek@Drone:~/tmp/helloAndroid$ mvn clean install android:deploy 
    ...
    [INFO] 279 KB/s (14872 bytes in 0.051s)
     pkg: /data/local/tmp/helloAndroid-1.0-SNAPSHOT.apk
    Failure [INSTALL_FAILED_INVALID_APK]
    [INFO] ------------------------------------------------------------------------
    [ERROR] BUILD ERROR
    [INFO] ------------------------------------------------------------------------
    

    I also tried to deploy the APK file manually (using the ADB tool) but Android emulator still claims that the package is broken. I assume then that the current android-quickstart archetype is broken.

    My workaround for the broken android artefact is to download zipped samples from the android-maven plug-in site and use Scala example as a template for my new project. As a bonus, Scala sample comes with tests, Scala language support and ProGuard obfuscator configured.

    Now just start your Android emulator, go to the directory of the project of yours, build the project and deploy it to the running emulator.

    hekonsek@Drone:~$ cd jayway-maven-android-plugin-samples/scala
    hekonsek@Drone:~/jayway-maven-android-plugin-samples/scala$ mvn clean install android:deploy
    ...
    [INFO] [android:deploy {execution: default-cli}]
    ...
    [INFO] 170 KB/s (8959 bytes in 0.051s)
     pkg: /data/local/tmp/Scala-1.0.0-SNAPSHOT.apk
    Success
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------
    

    Now enjoy your new Android application deployed and running on the emulator.