Building GitHub projects with Jenkins, Maven and SonarQube 5.2 on OpenShift

Time for an update of the post Building GitHub projects with Jenkins, Maven and SonarQube 4.1.1 on OpenShift, because SonarQube 5.2 is out: It’s the first version since 4.1.1 that can be run on OpenShift. That is, it’s the first version of SonarQube 5 and the first one that contains Elasticsearch and many other features that are now available on OpenShift!
Interested? Then let’s see how to set up SonarQube on OpenShift.

  • If you’re starting from scratch, just skip to this section.
  • If you got a running instance of SonarQube
    • make sure to back up you instance before you continue:
      rhc snapshot save -a <application name>--filepath <backup destination>
      or
      ssh <UID>@<application name>-<yourAccount>.rhcloud.com 'snapshot' > sonar.tar.gz
    • Then pull the git repository just like in step 2,
    • wait until the app has started and visit
      https://sonar-<yourAccount>.rhcloud.com/setup

      SonarQube will update it’s database during the process.

    • If you followed this post to set up your SonarQube instance and therefore use an SSH tunnel to access the SonarQube database, note that you can now get rid of this workaround. From SonarQube 5.2 the analyses can be run without direct contact to the database.
      That is, you can also remove the database connection from your the configuration of the SonarQube plugin in jenkins.

Install new SonarQube instance

To install SonarQube 5.2, execute the following steps on your machine:

  1. rhc app create sonar diy-0.1 postgresql-9.2

    Make sure to remember the login and passwords!

  2. git rm -r diy .openshift misc README.md
    git remote add upstream -m master https://github.com/schnatterer/openshift-sonarqube.git
    git pull -s recursive -X theirs upstream master
    git push
    
  3. Login to your SonarQube instance at
    http://sonar-<yourAccount>.rhcloud.com/

    Note that the initial setup may take some minutes. So be patient.
    The default login and passwords are admin / admin.
    You might want to change the password right away!

Basic installation Jenkins

Basically, the following is an updated (and a lot simpler) version of my post about SonarQube 4.1.1.

  1. Create Jenkins app
    rhc app create jenkins jenkins-1
  2. Install Plugins
    Browse to Update Center

    https://jenkins-<yourAccount>.rhcloud.com/pluginManager/advanced

    and hit Check Now (as described here).
    Then go to the Available tab and install

    1. Sonar Plugin,
    2. GitHub plugin,
    3. embeddable-build-status (if you’d like to include those nifty build badges in you README.md).

    Then hit Install without restart or Download and install after restart. If necessary, you can restart your app anytime like so

    rhc app restart -a jenkins
  3. Set up maven settings.xml to a writable location.
    • SSH to Jenkins
      mkdir $OPENSHIFT_DATA_DIR/.m2
      echo -e "&amp;amp;lt;settings&amp;amp;gt;&amp;amp;lt;localRepository&amp;amp;gt;$OPENSHIFT_DATA_DIR/.m2&amp;amp;lt;/localRepository&amp;amp;gt;&amp;amp;lt;/settings&amp;amp;gt;" &amp;amp;gt; $OPENSHIFT_DATA_DIR/.m2/settings.xml
      
    • Browse to Configure System
      https://jenkins-<yourAccount>.rhcloud.com/configure

      Default settings provider: Settings file in file system
      File path=$OPENSHIFT_DATA_DIR/.m2/settings.xml

  4. Either see my post on how to introduce a dedicated slave node to this setup or
    set up the Jenkins master to run its own builds as follows (not recommended on small gears, as you might run out of memory pretty fast during builds):
    Go to Configure System

    https://jenkins-<yourAccount>.rhcloud.com/configure

    and set
    # of executors: 1

  5. Setup sonar plugin (the following bases on SonarQube Plugin 2.3 for Jenkins)
    On the Jenkins frontend, go to Configure System

    https://jenkins-<yourAccount>.rhcloud.com/configure
    • Global properties,
      tick Environment variables
      Click Add
      name=SONAR_USER_HOME
      value=$OPENSHIFT_DATA_DIR
      See here for more information.
    • Setup the Runner:
      Navigate to SonarQube Runner
      Click Add SonarQube Runner
      Name=<be creative>
    • Then set up the plugin itself
      Navigate to SonarQube
      tick Enable injection of SonarQube server configuration as build environment variables
      and set the following
      Name=<be creative>
      Server URL:

      http://sonar-<yourAccount>.rhcloud.com/

      Sonar account login: admin
      Sonar account password: <your pw> (default: admin)

    • Hit Save

Configure build for a repository

Now lets set up our first build.

  1. Go to
    https://jenkins-<yourAccount>.rhcloud.com/view/All/newJob

    Item name: <your Project name>
    (Unfortunately, Maven projects do not work due to OpenShift’s restrictions.)
    Hit OK

  2. On the next Screen
    GitHub project:

    https://github.com/<your user>/<your repo>/

    Source Code Management:

    https://github.com/<your user>/<your repo>.git

    Branch Specifier (blank for 'any'): origin/master
    Build Triggers: Tick  Build when a change is pushed to GitHub
    Build Environment: Tick Prepare SonarQube Scanner environment
    Build | Execute Shell

    cd $WORKSPACE
    # Start the actual build
    mvn clean package  $SONAR_MAVEN_GOAL --settings $OPENSHIFT_DATA_DIR/.m2/settings.xml -Dsonar.host.url=$SONAR_HOST_URL
    
  3. I’d also recommend the following actions
    Post-build Actions| Add post-build action| Publish JUnit test result report
    Test report XMLs=target/surefire-reports/TEST-.xml*
    Post-build Actions| Add post-build action| E-mail Notification
    Recipients=<your email address>
  4. Hit Apply.
  5. Finally, press Save and start you first build. Check Jenkins console output for errors. If everything succeeds you should see the result of the project’s analysis on SonarQube’s dashboard.

Using Custom Maven / JDK version when building with Jenkins on OpenShift

[EDIT (2016-06-02): OpenShift now provides different JDK “alternatives”, e.g.

/etc/alternatives/java_sdk_1.8.0

So you might want to skip the steps bellow, regarding a custom JDK. The steps described for using a custom maven still apply, however.

]

In previous posts I pointed out how to build GitHub projects with Jenkins, Maven and SonarQube and how to run these builds on dedicated Jenkins slaves. The following shows how to replace the “stock” versions of maven and JDK that are provided by OpenShift.

At the time of writing OpenShift features Maven 3.0.4 and OpenJDK Server 1.7.0_85. Why would you want to change those? Best example is a Java8 project to be build on Jenkins. Can we just advise Jenkins to download the newest Oracle JDK and we’re good to go? Nope, it’s not that simple on OpenShift! Jenkins does download the new JDK, sets the JAVA_HOME variable and the correct PATH, but maven is always going to use the stock JDK. Why? Running this command provides the answer

$ cat `which mvn`
#!/bin/sh
prog=$(basename $0)
export JAVA_HOME=/usr/lib/jvm/java
export JAVACMD=$JAVA_HOME/bin/java
export M2_HOME=/usr/share/java/apache-maven-3.0.4
exec $M2_HOME/bin/$prog &amp;quot;$@&amp;quot;

The stock maven is setting its own environment variables that cannot be overridden by Jenkins!

So, in order to exchange the JDK, we need to exchange maven first.

  • SSH to the machines where your builds are executed (e.g. your slave node). The following example show what to do for maven 3.3.3:
    cd $OPENSHIFT_DATA_DIR
    mkdir maven
    cd maven
    wget http://apache.lauf-forum.at/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz
    tar -xvf apache-maven-3.3.3-bin.tar.gz
    rm apache-maven-3.3.3-bin.tar.gz
    
  • Edit maven config
    vi $OPENSHIFT_DATA_DIR/maven/apache-maven-3.3.3/conf/settings.xml
    

    Add the following to the <settings> tag (replace <UID> by your OpenShift UID first)

    <localRepository>/var/lib/openshift/<UID>/app-root/data/.m2</localRepository>

    (press i button for edit mode, insert, then press esc button, enter :wq, finally press return button)

  • Browse to
    https://jenkins-<yourAccount>.rhcloud.com/configure

    Set Environment variables
    PATH=$OPENSHIFT_DATA_DIR/maven/apache-maven-3.3.3/bin:$PATH
    M2_HOME=$OPENSHIFT_DATA_DIR/maven/apache-maven-3.3.3

  • And that’s it, your builds are now running on the custom maven!
    This allows for using a specific JDK in Jenkins. You could just choose a specific JDK via Jenkins console. This is comfortable, but has one disadvantage: It takes a lot of memory (approx. 600MB per JDK), because the JDK is stored twice – compressed in cache to be sent to slave and again uncompressed to be used on the master. If you got enough memory, you’re done here.

    However, In case you’re running a small gear with only 1GB of memory, you might want to save a bit of your precious memory. The following example shows how to do so for JDK 8 update 51 build 16.
    On SSH:

    cd $OPENSHIFT_DATA_DIR
    mkdir jdk
    cd jdk
    wget --no-check-certificate --no-cookies --header &amp;quot;Cookie: oraclelicense=accept-securebackup-cookie&amp;quot; http://download.oracle.com/otn-pub/java/jdk/8u51-b16/jdk-8u51-linux-x64.tar.gz
    tar -xvf jdk-8u51-linux-x64.tar.gz
    rm jdk-8u51-linux-x64.tar.gz
    
  • Then go to Jenkins
    https://jenkins-<yourAccount>.rhcloud.com/configure

    JDK installations | JDK
    Name=SlaveOnly-Custom-JDK8u51
    JAVA_HOME=$OPENSHIFT_DATA_DIR/jdk/jdk-8u51-linux-x64

Building GitHub projects on Jenkins slaves on OpenShift

This post showed how to build GitHub projects with Jenkins, Maven and SonarQube 4 on OpenShift. For starters, it used the Jenkins master node for running build jobs. However, when running on a small gear, the master node might run out of memory pretty fast, resulting in a reboot of the node during builds.

In order to resolve this issue, there are two options:

  • limitting the memory of the build or
  • running the build on a slave node.

As spawning additional nodes is easy in a PaaS context such as OpenShift and provides a better performance than running builds with small memory, the slave solution seems to be the better approach.

This post shows how.

  1. Create new DYI app as a slave node (a how-to can be found here), name the node e.g. slave
  2. Create node in Jenkins
    1. Go to Jenkins web UI and create new node:
      https://jenkins-<yourAccount>.rhcloud.com/computer/new
    2. Set the following values:
      Remote FS root:/app-root/data folder on slave. Typically this is /var/lib/openshift/<slave's UID>/app-root/data/jenkins, you can find out by SSHing to the slave node and calling

      echo $OPENSHIFT_DATA_DIR/app-root/data/jenkins

      Labels: Some label to use within builds to refer the node, e.g. OS Slave #1
      Host: the slave’s hostname, e.g. slave-<youraccount>.rhcloud.com

    3. Add Credentials
      username: <slave's UID>
      Private Key File:Path to a private key file that is authorized for your OpenShift account. In the first post this path was used: /var/lib/openshift/<UID of your jenkins>/app-root/data/git-ssh/id_rsa. Note: $OPENSHIFT_DATA_DIR seems not to work here.
      BTW: You can change the credentials any time later via this URL

      https://jenkins-<yourAccount>.rhcloud.com/credentials/
  3. Prepare slave node: Create same environment as on master in the first post
    1. Create folder structure
      mkdir $OPENSHIFT_DATA_DIR/jenkins
      mkdir $OPENSHIFT_DATA_DIR/.m2
      echo -e "&lt;settings&gt;&lt;localRepository&gt;$OPENSHIFT_DATA_DIR/.m2&lt;/localRepository&gt;&lt;/settings&gt;" &gt; $OPENSHIFT_DATA_DIR/.m2/settings.xml
      
    2. Copy SSH directory from master to same directory on slave, e.g.
      scp -rp -i $OPENSHIFT_DATA_DIR/.ssh $OPENSHIFT_DATA_DIR/.ssh &lt;slave's UID&gt;@slave-&lt;your account&gt;.rhcloud.com:app-root/data/.ssh
    3. As the different cartridges (jenkins and DIY) have different environment variables for their local IP addresses ($OPENSHIFT_JENKINS_IP vs $OPENSHIFT_DIY_IP) we’ll have to improvise at this point. There are two options: Either
      1. Replace all occurrences of $OPENSHIFT_JENKINS_IP
        In all builds and in

        https://jenkins-<yourAccount>.rhcloud.com/configure

        Sonar | Sonar installations
        Database URL: jdbc:postgresql://$OPENSHIFT_DIY_IP:15555/sonarqube
        or

      2. Create an $OPENSHIFT_JENKINS_IP environment variable on your slave machine
        rhc env set OPENSHIFT_JENKINS_IP=&lt;value of  $OPENSHIFT_DIY_IP&gt; -a slave

        You can find out the value of $OPENSHIFT_DIY_IP by SSHing to the slave and execute

        echo $OPENSHIFT_DIY_IP 
      3. I’d love to hear suggesstions that do better😉
  4. Adapt Build
    Easiest way is to not use the master at all.
    To do so, go to

    https://jenkins-<yourAccount>.rhcloud.com/configure

    and set # of executors to 0.
    Hit Apply

  5. Limit memory usage.
    Make sure the slave does not run out of memory (which leads to a restart of the node):
    Global properties | Environment variables
    name: MAVEN_OPTS
    value: -Xmx512m
    Hit Save.
  6. Now run a build. It should run on the slave and hopefully succeed🙂

See also Libor Krzyzanek’s Blog: Jenkins on Openshift wi… | JBoss Developer

Modernizing android UIs part 2: design support library, switches, action buttons

After finishing the migration from Actionbarsherlock to appcompat described in the first Post on modernizing android UIs, it turns out there are even more things to modernize in terms of android UIs.

Tabs and design support library

If you used Tabs within the ActionBar, after migrating to appcompat-v7 API 22 you might recognize a warning, that tells you that they are now deprecated.

In order to modernize those, you should use the design support library that was added to the Android SDK with API level 22. Similar to the appcompat -v7, the design support library provides backports of material design components of Android lollipop (5.x) for older versions of Android.

Here’s the steps that rid you of the deprecation warning

  • Add the design library to your eclipse workspace and link it with your project in pretty much the same way as appcompat described in the first Post. The library can be found on the following path: <sdkdir>/extras/android/support/design.
    Import it into eclipse as Existing Android Code Into Workspace, change the build target to level 22, and link the appcompat project with it.
  • Add the following to maven
    <dependency>
    <groupId>com.android.support</groupId>
    <artifactId>design</artifactId>
    <version>${android.compatibility.version}</version>
    <type>aar</type>
    </dependency>
    
  • Change your code to use the new TabLayout as described here. A complete example is the cheesesquare app: activity_main.xml, include_list_viewpager.xml, MainActivity.java
  • Once you’re done with this and have the design support library up an running, you could modernize your app by using more of the library’s features like navigation drawers, floating labels and buttons, snackbars, collapsing toolsbars, etc. See this blog post for more features.

The screenshots bellow show a before-after comparison – deprecated tabs vs material design tabs.

Tabs: design support library, API-22

Tabs: design support library, API-22

Tabs: AppCompat-v7, API-22, deprecated

Tabs: AppCompat-v7, API-22, deprecated

 

Checkboxes to switches

Android API level 14 introduces the switch component, that according to google should be used when only one option is available. For API levels < 14  there’s no such thing as switches. So we’ll have to rely on checkboxes there. Here’s how to replace checkbox preferences by switches for devices running API level 14 and above

  • In a preference XML, replace CheckBoxPreference by SwitchPreference (see commit ab16eb1997dfba743abcd488b6b20de71b5c3ff0 for an example).
  • However, If you want to keep compatibility with API levels < 14, you’re only choice is to keep redundant copies of the same preferences.xml in

    • res/xml/ that contains the preferences with CheckBoxPreferences and
    • res/xml-v14/ that contains the same file with SwitchPreferences.

Another before-after comparison is shown bellow – checkboxes vs switches.

AppCompat-v7, API-22 with checkboxes

Preferences: AppCompat-v7, with checkboxes

AppCompat-v7, API-22 with switches

AppCompat-v7, API-22 with switches

Using Action Buttons

Action Buttons are icons that realize the most important actions on the actionBar if there is enough room to display them. These could have been used in Actionbarsherlock already, but if you still didn’t modernized them then it’s about time🙂

One reason for not using action buttons might be that you don’t have suitable icons. Here’s the solution: Google provides a huge amount of material design icons under open source (CC-BY) license. They can be found on this site, or you can just clone their git repository.

So it’s as easy as that

  • Choose proper icons for your actions and copy them to your res/drawable-xyz folders
  • Add icon tags to your menu.xml like so
        <item
            android:id="@+id/action_refresh"
            android:icon="@drawable/ic_refresh_white_24dp"
            android:title="@string/action_refresh"
            app:showAsAction="ifRoom"/>

And that’s it. See bellow for an example. For an example see the commit that realized this change.

AppCompat-v7, API-22, ActionBar with menu

AppCompat-v7, API-22, ActionBar with menu

AppCompat-v7, API-22, ActionBar with action buttons

AppCompat-v7, API-22, ActionBar with action buttons

Modernizing android UIs part 1: Migrating from Actionbarsherlock to Material Design

This post shows by example the steps that are necessary for migrating an android application from Actionbarsherlock to Material Design (introduced in android KitKat/Version 5.x/API level 21/22), while keeping compatibility with at least android Gingerbread/Version 2.3 /API level 9). It uses the appcompat-v7 library on API level 22. The app that was migrated (nusic) in this example is developed using Eclipse, Maven and RoboGuice.

Before-after comparison

Let’s begin with some before-after screenshots:

ActionBarSherlock

ActionBarSherlock

AppCompat-v7, API-22

AppCompat-v7, API-22

02-nusic-abs-prefs

Preferences: ActionBarSherlock

Preferences: AppCompat-v7, API-22

Preferences: AppCompat-v7, API-22

Basic migration (appcompat-v7)

The following lists the steps that were implemented in order to change the app as depicted in the screenshots above.

  • Update Android SDK Tools
  • Eclipse
    • Setup Eclipse project for appcompat described here.
    • Link your project with it. Right click on your project | Properties | Android | Library | Add
      eclipse-choose-appcompat
    • Remove action bar sherlock. Same menu as above.
  • Set Up Maven Build
    • <repositories>
      <repository>
      <id>android</id>
      <url>file://${env.ANDROID_HOME}/extras/android/m2repository</url>
      </repository>
      </repositories>
      
    • <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>appcompat-v7</artifactId>
      <version>${android.compatibility-v7.version}</version>
      <type>aar</type>
      </dependency>
      
  • Migrate from Actionbarsherlock to appcompat
    • styles.xml

      <!-- <style name="AppBaseTheme" parent="@style/Theme.Sherlock"> -->
       <style name="AppBaseTheme" parent="@style/Theme.AppCompat">
      
    • Replacing classes
      • RoboSherlockFragment -> RoboFragment
      • RoboSherlockFragmentActivity -> RoboActionBarActivity
      • RoboSherlockPreferenceActivity -> Write your own RoboAppCompatPreferenceActivity that looks like this (or as described here) but is derived from RoboPreferenceActivity (see here for the class that was used in the example).
        Then derive your class from it as before with RoboSherlockPreferenceActivity.
    • Replacing methods
      • getSherlockActivity() -> getActivity()
      • getSupportMenuInflater() -> getMenuInflater()
    • Fixing imports
      • android.view.Menu
      • android.support.v7.app.ActionBar
    • Updating proguard.cfg
      • Remove actionbarsherlock
      • Add
        # support4, appcompat-v7, design support
        -dontwarn android.support.**
        -keep class android.support.** { *; }
        -keep interface android.support.** { *; }
        

For further info please see

iTunes: Exporting playlists with relative paths

TL;DR; A way of exporting iTunes playlists with relative paths is described here.

iTunes Export

Once upon a time I wrote a little tool for exporting playlists from Songbird/Nightinale. After migrating to iTunes, I was looking for a tool that provides the same functionality for iTunes. Fortunately, there already is one: iTunes Export. It’s twofold – you can either use a UI or a console version. I’m more the console type of guy, so my choice is clear. The latest release, version 2.2.2, was released in 2010, almost 5 years ago… and it still works with iTunes 12.1.2 – it’s a miracle! And it’s fast – my approximately 100 playlists are exported in less than 2 minutes.

Relative Playlist workaround

Among all those parameters of iTunes export, there is none for creating relative playlists, though. However, we can use a workaround for achieving this, by combining the musicPath and musicPathOld parameters. Here’s what the doc says:

  • musicPath
    iTunes Export will use the absolute location of your music files in the playlist. iTunes Export accepts a command line parameter that will override this default. Example:

    java -jar itunesexport.jar -musicPath="c:\My Music Directory"
  • musicPathOld
    Tunes Export will only apply the prefix to tracks stored in the directory configured in iTunes as the iTunes Music Folder location. Files stored in a different directory will not have the prefix applied.If you only wish to override a portion of the music path you can specifi the musicPathOld parameter. iTunes Export will replace this path with the musicPath parameter instead of replacing the default music path.

    java -jar itunesexport.jar -musicPathOld="c:\My Old Path"

A bit complicated, eh?!

Exporting playlists with relative paths by example

I’ll point out how we can use those parameters by a small example. Imagine the following folder structure

D:\Music\
  Playlists\
  Artist1\ 
    Song1.ext
  Artist2\
    Album\
      Song2.ext
  iTunes
    iTunes Library.xml

If we had a playlist call playlistX that contained Song1 and Song2 (anyone remember a band called Blur?🙂 ) and we would export it without further parameters to the Playlists folder, it would look like this:

D:\Music\Artist1\Song1.ext
D:\Music\Artist2\Album\Song2.ext

What we’re going to do is replace the absolute part with a relative one (in respect to the destination folder for playlists). In our example: Replace “D:\Music” by “..” because it’s the parent folder of “D:\Music\Playlists“. That’s exactly what the parameters mentioned above are for! musicPathOld is the the part that is going to be replaced by musicPath. Speaking of which, our call to iTunesExport looks like this:

java -jar itunesexport.jar -library="D:\Music\iTunes\iTunes Library.xml" -outputDir="D:\Music\Playlists" -musicPath=".." -musicPathOld="D:\Music"

and results in the file D:\Music\Playlists\playlistX.m3u

..\Artist1\Song1.ext
..\Artist2\Album\Song2.ext

Migrating from Songbird/Nightingale to iTunes

TL;DR; If you still use Songbird or Nightingale and want to migrate your music database to iTunes, start reading here.

Bye-bye Songbird, bye-bye Nightingale

Is anyone out there still using Nightingale or even Songbird? I started using Songbird in 2009 (or even earlier) and switched to Nightingale in 2013. All that time I loved the open source approach of both applications and even contrtibuted a bit myself. However, there also were a lot of drawbacks like performance, incompatibilities of addons after each new version, etc. Speaking of addons – the idea of a modular media player that is extensible just like Firefox or Thunderbird is wonderful. However, it seems to me there’s not much of a community left that releases addons for Nightingale. One of my favorites used to be MLyrics, which was last released in 2013 and doesn’t work properly anymore in the current version of Nightingale (at least for me). Still, there seems to be some development going on. Same goes for the core media player software itself: We all know that Songbird was discontinued in 2013 and the last release of Nightingale was published in January, 2014. Even though there also seems to be some development going on, I lost hope that there will be better usability at some point. So I finally decided with a heavy heart to move on. Nevertheless, I’d like to say thank you to all the Nightingale developers for their strong efforts to keep the dream of a real open source alternative for iTunes alive.

Is there a better alternative to Nightingale? That question I cannot answer properly. My reasons for migrating to iTunes are that it has been maintained by a huge company for years and it’s one of the most popular media players around. So hopefully, it might get along better with my rather huge media library in terms of performance. Plus it is the only tool that is capable of feeding my iPod Nano 6:-/

Technical approaches of migrating to iTunes

Leaving sentimentality behind – how to migrate from Songbird/Nightingale to iTunes?

One of the nice things about Songbird/Nightingale is their SQLite database. I already worked with it before when creating a playlist exporter for Songbird using the java programming language. It’s always a good idea not to reinvent the wheel. So after extracting the database wrapper into a separate project – songbirdDbApi4j (right now, I really wonder why I named it like this😮 ) – we’re halfway done with the Songbird to iTunes migration. Almost.

The other half – importing to iTunes was a bit more challenging. iTunes stores its database in an XML file. So one approach is to access this XML directly, just like tools such as iTunesExport. However, this file is generated by iTunes merely for the purpose of exporting, the actual database is stored in the ITL file. It would be possible to recreate the ITL from the XML, but this approach is not very convenient. So a different approach might be more suitable here: on Windows, iTunes offers a COM Interface. It’s poorly documented but fortunately, the developers of COM4j implemented it as one of their sample projects. In order to ease the use of this API, I create a very basic Java wrapper for iTunes’ COM API (itunes4j).

Almost done! What’s missing is a bit of glue logic that reads all files, some of their attributes and all playlists from songbird using songbirdDbApi4j and adds them to iTunes via iTunes4j.

Migrating to iTunes

After a lot of empirical studies and nightly test migrations, I’m proud to present a tool for migrating from songbird to iTunes: songbird2itunes. In case there happen to be any other Nightingale survivors out there that run on Windows and would like to migrate their music database to iTunes, you might just give it a go!

I did my best to make it a resilient migration tool. Still, there might be errors. So:

  1. Double check if you really want to leave Nightingale behind
  2. Make sure to read the wiki first. If you’re sure you want to do this, start the migration as described there.
  3. When the migration is done, check if the statistics show any warnings.
  4. If so, look for WARN in the songbird2itunes.log and see if those are not critical for you.
  5. In case of error, please fix it and contribute🙂
  6. Manually check your new iTunes library, making sure everything is as expected