Saturday, April 5, 2014

Raspberry Pi Information Radiator: Booting into a Browser

The third post in a series for building an information radiator using the raspberry pi, today we'll look at an approach for making a raspberry pi (running raspbian) boot up directly into a web browser. This was necessary for the information radiator since it was based on Dashing, a Ruby-based web application. While there were a number of articles describing how to boot into a browser, none of them worked in a way that was both simple and worked reliably.

The Application Script


So that I didn't have to debug the application startup and the boot process together, I developed a simple, but effective startup script for the application. It assumes there is a graphical environment running before it starts. The simple script starts dashing, waits for it to be available via HTTP and then starts the midori web browser in application mode, using our dashboard URL. I created the script in the pi user's home directory as $HOME/start-dashboard.bash.
First, let's setup the script to exit immediately on failure of a command:
 
 set -o errexit  

Now, let's start Dashing:

 URL=http://localhost:3030/sampletv  
  
 ##  
 # Start the dashboard, if URL is not already available  
 ##  
 if [ "$(curl --output /dev/null --silent -w '%{http_code}' --fail $URL)" != "200" ]; then  
  cd $HOME/dashing_sample  
  dashing start >& /dev/null &  
 fi    

Starting the application took much longer than starting the web browser. This meant that the browser loaded and showed "page not found" response. At least one other browser boot approach I found used midori's -i flag to periodically reload the browser. This would have worked except that the Dashing page loads take long enough on the pi that reloading periodically would have looked awful. It also would have shown the 404 page until Dashing started up. Rather than immediately starting the browser, I decided to simply wait until the dashboard URL was available to start the browser:


 ##  
 # Wait until the dashboard is up and running  
 ##  
 until [ "$(curl --output /dev/null --silent -w '%{http_code}' --fail $URL)" == "200" ]; do  
  echo -n "Waiting for ${URL}..."  
  sleep 2  
 done  
   
 echo "Starting web browser..."  
 midori -e Fullscreen --app "$URL"  
   

With that, our application startup script is complete. It starts Dashing, waits for our dashboard to be available over HTTP and then starts the web browser in app mode using our dashboard URL. All we need to do now is to use it during the raspberry pi boot process. The complete script:

 #!/bin/bash  
   
 set -o errexit  
   
 URL=http://localhost:3030/sampletv  
   
 ##  
 # Start the dashboard, if URL is not already available  
 ##  
 if [ "$(curl --output /dev/null --silent -w '%{http_code}' --fail $URL)" != "200" ]; then  
  cd $HOME/dashing_sample  
  dashing start >& /dev/null &  
 fi  
   
 ##  
 # Wait until the dashboard is up and running  
 ##  
 until [ "$(curl --output /dev/null --silent -w '%{http_code}' --fail $URL)" == "200" ]; do  
  echo -n "Waiting for ${URL}..."  
  sleep 2  
 done  
   
 echo "Starting web browser..."  
 midori -e Fullscreen --app "$URL"  
   

Hide the Cursor with Unclutter


By installing the unclutter package, the cursor will hide itself if left inactive for a short period. To clean up the interface by automatically hiding the cursor, install unclutter:

 sudo apt-get install unclutter  

Starting the App using LXDE's Autostart


At the time of this post, raspbian ships with the lightweight X11 desktop environment, or LXDE. We can configure the pi user's LXDE autostart setup to run our application startup script automatically. This leaves the default LXDE autostart configuration intact. First we have to create a user autostart file:

 # create an LXDE config directory for the pi user  
 mkdir -p $HOME/.config/lxsession/LXDE  
   
 # Create a new autostart file using your text editor
 vi $HOME/.config/lxsession/LXDE/autostart  

Then using our text editor, we add the following to our autostart configuration:

 # Turn off the screensaver  
 xset s off  
   
 # Disable blanking the screen  
 xset s noblank  
   
 # Disable display power management features  
 xset -dpms  
   
 # Run dashboard application  
 @/home/pi/start-dashboard.bash  

The xset command is a program that allows us to change the graphical environment's screen saver and power management features. We use them here to make the screen stay on 100% of the time. If we did not do this, after a period of inactivity a screensaver would start, the screen would blank or would be powered down. The xset command is not installed by default. It is part of the x11-server-utils package. To install it:


 # Install x11-server-utils to for xset command  
 sudo apt-get install x11-xserver-utils  

With this, starting the graphical environment as the pi user will automatically start our application. At this point, you can choose to configure booting into the graphical environment any way you like. I opted for manually configure it using /etc/rc.local and disabled the normal desktop tools.

Disabling LXDE Desktop Tools


While I didn't have to, I chose to disable the usual desktop tools that start with LXDE. I didn't want to spend the extra resources since the tools weren't going to be used in kiosk mode. To do this I edited the system-wide LXDE autostart file, /etc/xdg/lxsession/LXDE/autostart, and commented out the usual tools:

 ##  
 # The original autostart setup  
 ##  
 #@lxpanel --profile LXDE  
 #@pcmanfm --desktop --profile LXDE  
 #@xscreensaver -no-splash# Install x11-server-utils to for xset command  

If you find yourself needing the full desktop environment later, you need only uncomment these lines and restart the desktop environment.

Starting X11 Using Rc.local


Rather than use raspi-config or /etc/inittab to automatically boot into the graphical environment, I opted for simply starting X11 as the pi user in /etc/rc.local:

 #!/bin/sh -e  
 #  
 # rc.local  
 #  
 # This script is executed at the end of each multiuser runlevel.  
 # Make sure that the script will "exit 0" on success or any other  
 # value on error.  
 #  
 # In order to enable or disable this script just change the execution  
 # bits.  
 #  
 # By default this script does nothing.  
   
 # Start X11 as the pi user  
 su -l pi -c startx  
   
 exit 0  

At this point, you should be able to reboot your raspberry pi and the application should start, the browser should start in application mode, and the screen should not go blank or disable automatically.

Friday, April 4, 2014

Raspberry Pi Information Radiator: Streaming Music

In my last post, I outlined a project I have been working on for building an information radiator using the raspberry pi. For the last few days, I have been using this for my own needs and I have noted that having the information on constant display has worked as a constant reminder and motivator. I quickly noticed the lack of the right metrics, like my overall GitHub and blogging activity, and I am currently working on adding and improving them. Nice!

I also recognized an opportunity to utilize the always-on nature of the radiator more completely. I  like to work to music and this device is always on and has audio hardware powered and ready-to-use (or so I guessed). While I could use it to signal updates to the display or something else purely functional, I figured, why do something functional when it is more fun to play internet radio?

Oh yeah. I'm not getting to those tasks on my task list... right. (it works!)

Since this was surprisingly quick, easy and appeals to the command-line lovers out there (my peeps), I figured I would share it.

Installing CMus

First, we need a tool for playing audio. There are surprisingly many music players for linux. I did not spend much time considering the alternatives. I just used CMus. It heralded command line usage and supported a vi-like command-line interface (I love you emacs, but you are absurdly fat for a command-line editor). Interestingly enough, I found what may be a more direct approach to what I will describe here using mpd (and it can be controlled from vim with vimmpc!). The message here is that this is not the only approach, or even the best. With that said, to install CMus was simple from raspbian:

 # Install CMus using apt  
 sudo apt-get install cmus  

Forcing audio through HDMI

For some reason the audio wasn't working. Fortunately, I noticed settings in the rapsi-config tool for audio and there was an option to force audio through HDMI. After enabling this setting, everything started working.

 # force audio through HDMI  
 sudo raspi-config  

The setting is under 'Advanced Settings' => 'Audio' => 'Force HDMI'. Once I enabled this, I did not have to reboot the device, though your mileage may vary.

Playing an Internet Radio Station

To test out the audio, I quickly searched the icecast stream directory for a reggae station. Once I found a station I could live with, I copied the M3U link location using my web browser. I then started CMus and added the file:
 # Start the player  
 cmus  
 # While you are in the program, type  
 :add url http://dir.xiph.org/listen/4032882/listen.m3u  

The station was added as <Stream>. To start playing it, I simply used arrow keys to select it and hit Enter. Once it was buffered, I heard Bob Marley singing to me from my television. However, when I quit the program the audio stopped immediately. Screen to the rescue!

Using Screen to run CMus in the Background

If you haven't used screen to detach from long-running processes before, try it. It's an awesome tool. It effectively allows you to detach and reattach to a terminal from different sessions. Did I say it was awesome already? It saved my sanity a few times doing OS installs over unreliable connections working in Kenya. After about the third time being disconnected and having to start over, I found this tool. Anyway, I quickly recognized it would work for running CMus in the background as well.

To install it:

 # Install screen using apt  
 sudo apt-get screen  

To start and detach from CMus:

 # Start screen  
 screen  
 # Start CMus  
 cmus  
 # To detach once you started your audio, hit ctrl-a then ctrl-d  

Once you do this, you will be back to a command prompt and you should notice the audio continues playing! You can quit your terminal session, and it will continue running. When you are ready to access the program again, simply login and do the following:

 # Reattach to the previously detached session  
 screen -r  

There is a lot more flexibility and power screen can give you, but this will be enough to run CMus in the background.

Using CMus Remote

With what we already setup, you could operate CMus simply by attaching and reattaching to the running processing using screen. However, CMus provides a program called cmus-remote that allows you to communicate to the running program through a named pipe. If you don't know what that means, that's ok, it enables you to run commands and control CMus without having to attach to the running terminal in screen. Just login and you can do things like the following:

 # Stop the player  
 cmus-remote --stop  
 # Start the player  
 cmus-remote --play  
 # Query the status of the player  
 cmus-remote --query  
 # Sample output from querying  
 status playing  
 file http://dir.xiph.org/listen/4032882/listen.m3u  
 duration -1  
 position 21  
 tag title BobMarley  
 tag genre reggae  
 tag comment http://bobmarley.blogdeouf.com  
 set aaa_mode all  
 set continue true  
 set play_library true  
 set play_sorted false  
 set replaygain disabled  
 set replaygain_limit true  
 set replaygain_preamp 6.000000  
 set repeat false  
 set repeat_current false  
 set shuffle false  
 set softvol false  
 set vol_left 100  
 set vol_right 100  
 # Set the volume  
 cmus-remote -v 80%  
 cmus-remote -v 100%  

One thing I did note was that for some reason, setting the volume to anything below 80% with my setup seemed to mute the audio entirely.

Improving On It

This enables you to play audio, but it does force you to login to the raspberry pi to do it. This worked for me, but I could definitely see wanting to improve on this. Some specific ideas I had were controlling CMus via an IRC bot and stopping and starting based on a work schedule using cron. You might also use something like mpd to eliminate the need for using screen entirely. In any case, it is a simple approach that may spark some of your own ideas. Enjoy!

Wednesday, April 2, 2014

An Information Radiator using Dashing and the Raspberry Pi

For those unfamiliar with the term information radiator, it is similar to what some call information dashboards. The term information radiator apparently comes from the Agile software development methodologies, as our friends over at Atlassian explain:
An information radiator is a large, highly visible display used by software development teams to track progress. The term was first coined by Alistair Cockburn, one of the judges for the Ultimate Wallboard contest, in his book as follows:
“An Information radiator is a display posted in a place where people can see it as they work or walk by. It shows readers information they care about without having to ask anyone a question. This means more communication with fewer interruptions."
There are good things that come out of putting key pieces of information on public display. Such as a greater awareness and inevitable challenging of the metrics, conversations about, understanding of and stake in the quality and relevance of tracked metrics, and some creative solutions for better measuring and improving your work, especially if you find yourself on the right team.

I found the above description, and the site, when scouring the internet for a useful electronic wallboard setup for teams using Jira Agile. I was searching for an information radiator without knowing the name for it and was happy to have found myself in good company. For my purposes, I was interested in broadcasting the following:

  • The number of days left in the Sprint
  • The Sprint burn-down chart, showing the completion rate and remaining work in the sprint
  • The task board, showing what state the various tasks and stories are in
  • Projected release dates (as a calendar), for better overall awareness of projected release timings

Others metrics like code review, quality or test metrics would have been nice, too. However, since they were not directly relevant to what we were struggling with the most I felt it would have worked against my goal of increasing focus and clarity. More information would have worked against gaining an intuition for the key metrics and what they meant.

I pulled together a quick prototype based on the Atlassian article, which was easy with the Jira dashboards and the open social gadgets. Essentially, all of these pieces were already there and the Atlassian plugin framework enabled extending the platform with more gadgets if I needed more. The Jira dashboards were optimized for HD television resolutions, so I just needed a device to display the dashboard when I was finished. After doing some research, I decided I would use a simple mounted HD television driven by a raspberry pi.

However, I didn't have time to build the device before needing to part with the team. Nevertheless, I soon found a need for a similar device again. This time however, I didn't have all the information in Jira. Fortunately, the heroic developers from Shopify built an information dashboard tool called Dashing. By mashing up apis from different sources, and a little elbow grease patching up and rewriting widgets, I was able to design a dashboard that I felt was good enough and could be refined further.

Dashing on the Raspberry Pi
Much like the Jira dashboards, I could easily build dashboards for an HD resolution (1080p), so again it was then just a matter of getting a device to display it. With some configuration, I was able to get a fairly minimal install on a rasperry pi. The big benefits here are size, expense and power consumption. I'll post more details on how I configured Dashing and the raspberry pi shortly. Until then, here is the result of my initial pass. The information is being pulled together from GitHub, Asana, Yahoo! weather, Google Calendar, BBC News, and Twitter.

Continue reading for more detail on how to configure a raspberry pi with Dashing, booting into a browser, building a dashboard and even how you can stream music from your dashboard. I have also published the full source code on GitHub. 

Saturday, September 21, 2013

How management consultants will kill technology innovation

Recently I was forwarded an article by a colleague of mine. It was an article published by McKinsey&Company, with the subject line "FW: Improving application development". Ironically, after reading the article, I was left with a stark vision of the future of technology with McKinsey consultants in the driver's seat. Spoiler: it would look something like an assembly line.

The article, titled "Enhancing the efficiency and effectiveness of application development", introduces a pedestrian concept of measuring the input side of application development as a means to measure productivity on the output side. The concept is an attempt to quantify use cases with a point system and the points are used to measure productivity. While there was nothing inherently problematic with the concept in the abstract, reading the article raised huge red flags.

According to the article:

"organizations often don’t have a robust way to gather and organize functional and technical requirements for application-development projects. Instead, they list requirements in what often amounts to little more than a loosely structured laundry list. Organizations may have used this laundry-list approach over a long period of time, and it thus may be deeply entrenched."

The diction used suggests that the reason that the requirements gathering is not robust and organized is a function of inefficiency of the individuals or processes used to gather them. A major flaw in this line of thinking is often the organization itself has an insufficient understanding of the root problems they face and how to solve them. The word entrenched suggests irrationality, with the implication that there may be something of a hostile takeover required to correct the problem. But, what is the problem?


"organizations find it difficult to fully and accurately capture requirements and align them with the needs of their internal or external business clients. Their application-development projects tend to suffer the inefficiencies of shifting priorities, last-minute change requests, and dissatisfied business users. In our experience, these changes often amount to cost overruns of 30 to 100 percent... ...use cases provide a logical and structured way to organize the functional requirements of an application-development project. Each use case is a description of a scenario under which the user of an application interacts with that application. For example, a UC for an online-banking application might describe each of the steps that a bank customer follows to log into her account and check the balance of available funds, as well as the transactions involved when that application calls on a database to pull up the stored information."

According to authors, the problem is that the requirements aren't logical or structured. That lack of logic and structure is responsible for project overruns. However, use cases have long been employed for documenting requirements during object-oriented analysis using UML use case diagrams. This approach is structured. A well-known benefit of use case diagrams is that they are commonly understood by business people lacking technical backgrounds. However, logic and structure is not missing. It is converging on an understanding of the root problem, a solution (or solutions) and accurately predicting time and resources involved in implementing it. Project analyses are commonly logical and structured. However, overruns come from a changing understanding of the problem(s) or the resources required to solve them.

Traditional waterfall design promoted large up-front analysis, assuming that it was just a matter of a robust organization and structure to understanding the problem and costs involved. However, modern methods start with the assumption that it is natural and expected that the solution and estimates change as you start to better understand what problem you are trying to address and the details involved in a solution. Initial predictions matter less because they are based on insufficient understanding. Modern methods try to incorporate this learning to deliver concrete working software, iteratively. The idea is  that all along you produce something you can potentially use.

From the sidebar, it appears the authors don't understand these methods.

"...where the primary purpose of SPs is to allocate the workload across the team. ...However, because SPs are based solely on gut feel, they are too subjective or too easy to game to compare different development teams or even the performance of a single team over multiple periods.
Use-case points (UCPs) represent a sweet spot between FPs and SPs. UCPs are easier to calculate than FPs, provide a similar level of accuracy and objectivity, and require far less overhead. At the same time, UCPs provide significantly more accuracy and objectivity than SPs, without unduly adding overhead."

Story points aren't an absolute because, if you are being honest with yourself, your true ability to define and estimate work is not good enough. You are more likely to be able to identify relative complexities, and ultimately, that's good enough to predict a velocity once you have established a baseline on real work with your team. The experience levels, problems, tools and techniques you have will drastically reduce the efficacy of an estimate taken from another company or team. However, if you estimate your entire backlog of identified work (stories) in relative terms, after measuring the velocity of the team you can estimate delivery dates. However, remember your understanding is changing as you learn more about your problem(s) and solution(s).

Trying to optimize productivity when you aren't ensuring that you regularly converge on the right problem(s) is misguided. Applying metrics based on poor assumptions and using it to steer decisions without a full awareness of the biases and limitations undermines the whole point of building something: to deliver something valuable. But then, how do you measure value? Maybe, we haven't done a good job of that one either.


There are people out there doing better, but not by mashing together old-school business thinking and antiquated software development practices. It is natural to fail to meet our expectations when they are unrealistic. Starting with an appreciation of how poor our initial understanding is and an ability to fail fast and pivot quickly with learning allows you to converge on something valuable. It might not be what you thought you needed, but it will be something of value. Repeatably delivering valuable things, not hitting Use Case Points estimates, will propel the world's next wild success story.

Supporting code review with Maven, Git, Jenkins and Atlassian Stash

I have to admit, the first time I used git it left a bad taste in my mouth. The commands seemed to promote using options in your default workflow and it felt overly complicated, like a tool designed by developers who love complexity. I chalked it up to the fact it was designed by Linux kernel hackers. I used the tool only when I had to, such as when contributing to projects hosted in GitHub, like Jenkins. It turned out, I was wrong. I was working with a different mental from the tool's designers and expecting the tool to feel natural to me

Recently, a colleague of mine sent a couple of videos that explain how git works. After watching them, the elegance and simplicity of the tool was obvious. Now, I am spending the weekend rushing to get a git repository manager, Atlassian Stash, integrated into our work flow in time to welcome a new team member with pre-integration code reviews; something that Git and Stash make extremely easy.

If you are interested in those videos, I can't recommend them more especially for Git skeptics:


Atlassian Stash and Code Review


I wanted to introduce code review into the core of my team's development loop. I have seen teams completely transformed by it. I have had success with patch-based review, but the exceptions like handling binary files and trying to update patches with conflicts for teams with reservations about review being too cumbersome is not recommended. It still has more benefits than drawbacks, but with negative stakeholders it can be like walking through a mine field. Distributed version control makes these exceptions a non-issue since a pull request can be integrated as-is, no patch-up intervention necessary.

When looking for a supporting tool, GitHub Enterprise was a natural choice, but the pricing was expensive especially for the size of my team. Alternatively, Atlassian Stash had extremely affordable pricing for the size of my team. The code viewer is admittedly more cumbersome than GitHub's, but is still better than the tools we were using before. More importantly, it handles the pull request work flow with reviewers and once you configure it, it integrates well with Jenkins and Jira.

Configuring Maven


Stash supports the SSH transport, and can simply add your SSH key to your user profile. Under Cygwin/Linux it's the normal SSH key authentication setup. Add your public (.pub) key under your user profile in Stash and clone an empty Stash repo. You can then setup Maven to use the repo by adding an SCM section in a project pom:

<scm>
  <developerConnection>
  scm:git:ssh://git@your.stash.host:7999/ex/example.git
  </developerConnection>
</scm>

By default, the Maven Git SCM provider will use this as both the fetch and push URL. You can optionally specify different push/fetch URLs.

Configuring Jenkins


Before you start, you will want to install the following:

  • Jenkins Maven Integration (included with recent Jenkins versions)
  • Jenkins Git Plugin
  • Stash Notifier Plugin

You'll need to configure key auth for Jenkins to clone the repo. You will also want to configure Stash settings for the notifier (Manage Jenkins->Configure System). Once you've done this, to set up a single branch build on 'master':

  • Source Code Managment: Git
  • Repository URL: ssh://git@your.stash.host:7999/ex/example.git
  • Name: origin
  • Refspec: +refs/heads/master:refs/remotes/origin/master
  • Branches to build: master
  • Checkout/merge to local branch (Advanced): master (required to use release plugin)
  • Repository browser: stash
  • Repository browser URL:  https://your.stash.host/projects/EX/repos/example
  • Build triggers: when snapshots dependencies are built, Poll SCM with long interval
  • Maven release build (if you are using it)
  • Post-build actions: Notify Stash Instance (reports build results back to Stash)

Pull-request Builds


There are multiple ways to configure this, including writing your own plugins. However, using another build you can publish build results to Stash pull requests. Create a new job and configure the following:

  • Source Code Managment: Git
  • Repository URL: ssh://git@your.stash.host:7999/ex/example.git
  • Name: origin
  • Refspec: +refs/pull-requests/*:refs/remotes/origin/pull-requests/*
  • Branches to build: origin/pull-requests/*/from
  • Repository browser: stash
  • Repository browser URL:  https://your.stash.host/projects/EX/repos/example
  • Build triggers: when snapshots dependencies are built, Poll SCM with long interval
  • Build: Goals and options = clean verify
  • Post-build actions: Notify Stash Instance (reports build results back to Stash)

Triggered Builds


This will work, but if you want to start the builds immediately upon pushed changes you need to configure a web hook in stash. In the repository settings, add the 'Stash Post-Receive Webhook to Jenkins'. Configure it with the following settings:

  • Jenkins URL: https://your.jenkins.host/
  • Git Repo URL: ssh://git@your.stash.host:7999/ex/example.git

The plugin tells your Jenkins server to poll immediately and a build will start if there are relevant changes to build. You could just trigger a build with a direct web hook to the job, but this will always trigger a build, regardless of whether the changes are for the branch(es) you are building.


How It Works


Using this setup, your master build publishes artifacts with approved changes to your repository. Your team integrates changes by merging submitted pull requests. When pull requests are submitted, Jenkins detects them and updates the pull request with the build status.This allows your reviewers to  review the code and allows them to see whether the pull request builds in advance.

Friday, August 16, 2013

Java8's Virtual Extension Methods - Fail?

After an interesting discussion at work last night, I wanted to check my mental model about the new Java 8 feature, virtual extension methods. After reading Anton Arhipov's article on the feature, I came to the conclusion that the feature was conceptually inconsistent and more surprisingly unsafe, effectively failing at a significant piece of the feature's intended purpose.

In Brian Goetz's presentation, he clearly states:
The whole point of this feature is being able to compatibly evolve APIs
He continues to describe that there are two types of compatibility involved, source and binary compatibility, that "The key operation we care about is adding new methods with defaults to existing interfaces" and that "We care more about avoiding binary incompatibilities than source incompatibilities". This goal is appropriate considering that a major motivation for the feature is adding support for forEach to existing collections classes without requiring they implement new methods and recompile to enable support under Java 8.
Brian's notion of binary compatibility puzzles me, considering he identifies the problem I realized after reading Anton's article. Brian states: 
Currently several vectors through which an “innocent” change to an interface can break code... Add an extension method which is identical to an extension method in another interface, and classes exist that implement both interfaces
Multiple inheritance was a primary motivator for interfaces in the Java language, and there are natural places where this situation would arise: for instance implementing similar interfaces for different frameworks. After arguing with coworkers about whether this would be an issue, I decided to test my hypothesis.

The experiment:
  • Create two interfaces
  • Create a class implementing both interfaces
  • Create a main class that dynamically loads the class, instantiates an object, casts the object to the respective interface types and calls the methods
  • Update the interfaces to add a default method with the same signature
  • Create a new main class that calls the inherited method
  • Run the main method with the class built against the original interface
 
interface Interface1 {
  void go1();
}
interface Interface2 {
  void go2();
}
class Class1 implements Interface1, Interface2 {
  void go1() {
    System.out.println("go1");
  }
  void go2() {
    System.out.println("go2");
  }
}
class Main {
  public static void main(String [] args) throws Exception {
    Object o1 = Class.forName("Class1").newInstance();
    Interface1 i1 = (Interface1)o1;
    i1.go1();
    Interface2 i2 = (Interface2)o1;
    i2.go2();
  }
}

Compiling and running the code under Java 6, we get the expected output:
go1
go2

I archived the classes to easily simulate what happens with class libraries. I can mix and match Java 6 implementations of Java 8 interfaces:
  • jre6ifaces.jar - contains Interface types (think java.util.List)
  • jre6usercode.jar - contains Class types (think your implementation of java.util.List)
  • jre6client.jar - contains the main class
I then reimplemented the existing interfaces to have default methods: 

interface Interface1 {
  void go1();
  default void stop() { System.out.println("stop1"); }
}
interface Interface2 {
  void go2();
  default void stop() { System.out.println("stop2"); }
}
I tried to recompile the existing class, which should inherit the functionality from the interfaces. I got an error, so the compiler is checking for this. The designers obviously knew of the problem and protect us from creating that situation for new code. However, remember the primary goal was extending existing code compatibly:

$ javac *.java
Class1.java:1: error: class Class1 inherits unrelated defaults for stop() from types Interface1 and Interface2
public class Class1 implements Interface1, Interface2 {
       ^
By specifying the method directly in the subclass, Interface1's stop implementation, we resolve the conflict and the compiler happily compiles our code. I changed the Main class to use the new method:

public class Main {
  public static void main(String [] args) throws Exception {
    Object c1 = Class.forName("Class1").newInstance();

    Interface1 i = (Interface1)c1;
    i.go1();

    i.stop();
    Interface2 j = (Interface2)c1;

    j.go2();
    j.stop();

  }
}
Again the output is what we would expect:
go1
stop1
go2
stop1
I then archived the java8 classes into jars, just like I did with the Java 6 ones:
  • jre8ifaces.jar - contains Interface types (think java.util.List)
  • jre8usercode.jar - contains Class types (think my impl of java.util.List)
  • jre8client.jar - contains the main class
Finally, I ran the following:

$ java -cp "jre8ifaces.jar;jre8client.jar;jre6usercode.jar" Main
This simulates a natural situation: 
  • ifaces represent the new collections interfaces in Java 8
  • client is new client code under Java 8 wanting to use the forEach loop with pre-Java 8 collections implementations
  • usercode are pre-Java 8 collections implementations that should run safely in the new runtime environment 
I received the following result:

$ java -cp "jre8ifaces.jar;jre8client.jar;jre6usercode.jar" Main
go1
Exception in thread "main" java.lang.AbstractMethodError: Conflicting default methods: Interface1.stop Interface2.stop
        at Class1.stop(Class1.java)
        at Main.main(Main.java:9)
So, despite everything passing static analysis by the compiler, previously defect-free code is failing unexpectedly at runtime under Java 8. Binary compatibility is not upheld. Taking this into account, reconsider the goals according to Oracle's Java language architect, Brian Goetz:
  • "The whole point of this feature is being able to compatibly evolve API"
  • "The key operation we care about is adding new methods with defaults to existing interfaces" 
  • "We care more about avoiding binary incompatibilities than source incompatibilities"
Do you think the goal was achieved?