A threaded Go language application with semaphores

After hearing about Go and its love of parallelism, I wanted to give it a try. I couldn’t think of any small projects that needed to be threaded until recently.  My employer uses an RPM system, but I’m using Ubuntu, which requires deb files.  Searching through the RPMs in a browser is a pain, so I wanted a small script that would search for me.  Here’s the script with server names changed.

package main

import (
  "bufio"
  "fmt"
  "http"
  "os"
  "regexp"
  "strings"
)

var servers = []string {
  "http://www.google.com/search?client=ubuntu&channel=fs&q=go+language&ie=utf-8&oe=utf-8",
  "http://golang.org/",
  "http://golang.org/doc/go_tutorial.html"}

var maxOpenRequests int = 3

var rpmRegexp = regexp.MustCompile("href=\"[^\"]+\"")

func main() {
  search := getSearchTerm()
  out := make(chan string)
  done := make(chan int)
  go printer(out)
  for _, url := range servers {
    go searchURL(search, url, out, done)
  }
  for i := 0; i < len(servers); i++ {
    <- done
  }
}

func getSearchTerm() string {
  args := os.Args
  if len(args) != 2 {
    die("Please enter one search term")
  }
  return args[1]
}

func die(message string) {
  fmt.Println(message)
  os.Exit(1)
}

func printer(out chan string) {
  for {
    fmt.Println(<- out)
  }
}

var requestSemaphore = make(chan int, maxOpenRequests) // Integer chanel with a maximum queue size

func searchURL(search string, url string, out chan string, done chan int) {
  requestSemaphore <- 1 // Block until put in the semaphore queue
  response, realURL, err := http.Get(url)
  if err == nil {
    bufferedReader := bufio.NewReader(response.Body)
    err = searchAll(search, bufferedReader, url, out)
    response.Body.Close()
  }
  if err != nil {
    die("Could not read from " + realURL + ":" + err.String())
  }
  <- requestSemaphore // Dequeue from the semaphore
  done <- 1 // Signal that function is done
}

func searchAll(search string, reader *bufio.Reader, httpRoot string, out chan string) (os.Error) {
  var error os.Error = nil;
  for {
    var line, err = reader.ReadString('\n')
    if err != nil {
      if err == os.EOF {
        break
      }
      return error
    }
    var hrefs = rpmRegexp.AllMatchesStringIter(line, 0)
    for href := range hrefs {
      start := strings.Index(href, "\"") + 1
      end := len(href) - 1
      packageFile := href[start : end]
      if strings.Index(packageFile, search) != -1 {
        out <- httpRoot + packageFile
      }
    }
  }
  return error
}

A quick overview

Go uses “channels” for communication among threads.

  1. The main thread creates two channels, one to receive search output and one to receive “done” responses when a child thread finishes.
  2. The main thread attaches the output channel to a simple function that prints to standard out.
  3. The main thread spawns one child thread per server, giving each the output and done channels.
  4. The main thread loops over the done channel once for each server, waiting until all requests are complete.
  5. Each child blocks immediately until space is available in a semaphore.
  6. The child performs the HTTP get, then searches the response for anything matching a regular expression.  Any matches are signaled back to the output channel.
  7. The child opens a space in the semaphore and signals to the main thread that it is done.

There isn’t much more to say.  The Go web site has great tutorials, so I don’t yet feel the need to write one.

By the way, if you’re searching for Go resources, be sure to search for “go language” and not “go”.  But then, that’s probably how you found this page ;)

package main

import (
“bufio”
“fmt”
“http”
“os”
“regexp”
“strings”
)

var servers = []string {
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS/”,
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS.extras/”,
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS.java/”}

var maxOpenRequests int = 3

var rpmRegexp = regexp.MustCompile(“href=\”[^\"]+\”")

func main() {
search := getSearchTerm()
out := make(chan string)
done := make(chan int)
go printer(out)
for _, url := range servers {
go searchURL(search, url, out, done)
}
for i := 0; i < len(servers); i++ {
<- done
}
}

func getSearchTerm() string {
args := os.Args
if len(args) != 2 {
die(“Please enter one search term”)
}
return args[1]
}

func die(message string) {
fmt.Println(message)
os.Exit(1)
}

func printer(out chan string) {
for {
fmt.Println(<- out)
}
}

var requestSemaphore = make(chan int, maxOpenRequests) // Integer chanel with a maximum queue size

func searchURL(search string, url string, out chan string, done chan int) {
requestSemaphore <- 1 // Block until put in the semaphore queue
response, realURL, err := http.Get(url)
if err == nil {
bufferedReader := bufio.NewReader(response.Body)
err = searchAll(search, bufferedReader, url, out)
response.Body.Close()
}
if err != nil {
die(“Could not read from ” + realURL + “:” + err.String())
}
<- requestSemaphore // Dequeue from the semaphore
done <- 1 // Signal that function is done
}

func searchAll(search string, reader *bufio.Reader, httpRoot string, out chan string) (os.Error) {
var error os.Error = nil;
for {
var line, err = reader.ReadString(‘\n’)
if err != nil {
if err == os.EOF {
break
}
return error
}
var hrefs = rpmRegexp.AllMatchesStringIter(line, 0)
for href := range hrefs {
start := strings.Index(href, “\”") + 1
end := len(href) – 1
packageFile := href[start : end]
if strings.Index(packageFile, search) != -1 {
out <- httpRoot + packageFile
}
}
}
return error
}

Posted in Go at May 21st, 2010. No Comments.

Python Package Structure with Unit Testing, Injection and Mocking

Python is a language that some people like and use.  I recently was given a small Python application and had to refactor it so that I could implement unit and functional tests.  It took me a while to find the resources and learn how to implement them, so I thought I’d write it up here.

* Please note that this is not a unit testing tutorial.  Those are plentiful and can be found elsewhere.  This describes setting up a professional Python project with a real package structure, injection and tests.

Python Project Structure

Python was conceived as a scripting language.  Unlike compiled languages like C or Java, Python files are designed to be directly runnable.

  • RunMe.java -p someargument < Not ok!
  • RunMe.py -p someargument < Ok!

This is convenient for small scripts, but doesn’t help applications.  Since you are intended to run .py files directly, Python projects should not have source (src) or binary (bin) folders.  Having a source folder makes a program difficult to run.  The root of the Python package structure should be the root of the project.

For the same reason, the test folder should not be separate.  It should be a package in the main project.  Since the root folder is the root package, you won’t have much choice.

Example

  • MyProject
    • __init__.py
    • model
      • __init__.py
      • user.py
    • service
      • __init__.py
      • user_service.py
      • ldap_user_service.py
    • test
      • __init__.py
      • unit
        • __init__.py
        • service
          • __init__.py
          • user_service_test.py
      • functional
        • __init__.py
        • service
          • __init__.py
          • user_service_test.py

If you’re new to Python, please note that those __init__.pys are required.  They tell Python which folders contain Python files.  This is Python’s way of allowing you to have other folders, such as config, that don’t contain source files.

Note

You should specify exactly one class per file.  It makes your code easier to find and read.

Injection with snake-guice

Injection is essential for unit tests.  In the example above, LDAPUserService may connect to an LDAP server to retrieve information, something we don’t want to happen in unit tests.

I’ve been using snake-guice and highly recommend it.

Install snake-guice, Mock and nose

If you don’t have it, grab a copy of easy install.  Then, $ sudo easy_install.py snake-guice Mock nose.  That installs packages from PyPI, the Python Package Index.  For those used to non-scripting languages, this may not seem like a great way to use external libraries.  Since Python is a scripting language, however, it’s the only way that makes sense.

Create a module and use it to instantiate your application

class ExampleModule:
  def configure(self, binder)
    binder.bind(UserService, to=LDAPUserService)
class ExampleRunner:
  user_service = None
 
  @inject(user_service=UserService)
  def __init__(self, user_service):
    self.user_service = user_service
 
  def main(user_service)
    self.user_service.login("name", "password")
injector = Injector(ExampleModule)
runner = injector.get_instance(ExampleRunner)

When get_instance is called, injector will use the ExampleModule to discover bindings.  Then, it will create an ExampleRunner, passing in arguments specified by @inject.

The setUp method of PyUnit tests should create an injector with a TestExampleModule, which should be configured to return mocks.

class TestExampleModule:
  def user_service = Mock()
 
  def configure(self, binder)
    binder.bind(UserService, to=user_service)
class ExampleTest(TestCase):
  application = None
 
  def setUp(self):
    Injector = Injector(TestExampleModule)
    self.application = injector.get_instance(ExampleApplication)
 
  def test_something(self):
    application.user_service.search.return_value = "expected"
    actual = application.user_service.search("any")
    self.assertEquals(expected, actual)

Since setUp is called before each test, each test method gets a fresh mock that it can configure any way it likes.

Similarly, a functional test module can be created that connects to a local or testing server.

Mocking with Mock

I recommend using Mock for mocking, which is why I had you install it earlier.  Be careful when searching for it because there appear to be two projects called Mock.

The Mock package is well documented.  Please go to the Mock site for more information.

Running Tests

For running tests, I recommend Nose.  To run your tests, open a command line and change to your root project folder.  Then, nosetests.  Nose will take care of adding the packages you installed earlier, snake-guice and Mock, to the Python path.  It will also find all tests, run them and report the results.  Handy!

$ cd ~/exampleproject
$ nosetests

To run only unit or functional tests, use the -w argument.

$ nosetests -w ./ ./test/unit
$ nosetests -w ./ ./test/functional

Is that all?

To those who have not used injection or mocks for testing, this may seem like a lot of work.  I hope you’ll try it, though, because it’s a one-time setup.  Once these good practices are in place, you’ll find that all of your code organization and testing becomes simple and almost automatic.  If I missed something or if you have any suggestions, please post below.

Posted in Python at February 6th, 2010. 2 Comments.

HTC T-Mobile G1 vs Motorola CLIQ

I owned a G1 for just over a year and it was lost or stolen.  Having used Android for so long, I couldn’t live without it for 7 months until I was eligible for an upgrade.  I stopped by the T-Mobile store to get a replacement G1, but was pleasantly surprised to find that the CLIQ was the same price.  I knew it was faster and had a headphone jack (yes!), so I picked it up.

It always takes time to get used to a new phone, but even after a month of use, I wasn’t blown away by the CLIQ.

  • The basics, things that you can read in the phone specs
    • The G1 has a larger screen.  It’s not a big difference on paper, but is quite noticeable in use.
    • The CLIQ has a headphone jack, meaning you can listen to music with standard earbuds or headphones or plug it in to your car’s stereo and charge it at the same time without having to buy and tote around a custom dongle.
  • Speed – CLIQ
    • Although they have the same processor, the CLIQ wins here pretty handily.  Even after all of the updates between Android 1.0 and 1.6, the G1 was always sluggish.  Some applications slowed it down so much that it became unusable and had to be rebooted.
  • Battery – CLIQ
    • The G1 had to be recharged at least once a day.  During a day of heavy use, it needed more than one charge.  The CLIQ won’t go for days on a charge like some non-smart phones, but it easily outlasts the G1.
  • Keyboard – G1
    • People may complain about the G1′s rotate-out-slider feature, but it allows the G1 a gigantic, easy-to-use keyboard by phone standards.  Traditional sliders, like the CLIQ’s, can only go so far up before they become wobbly and prone to breaking.  The G1′s screen is completely separate from the main body except for the connection at the bottom (or right), allowing it to slide much farther up.  The G1′s keys are also better designed.  They’re just as responsive as the CLIQ’s, but without the annoying, well, clicks made by the … CLIQ.
  • D-pad / Trackball – G1
    • The CLIQ’s directional pad works just as well as the G1′s trackball.  Each design has it’s benefits.  The trackball lets you zoom through text or selections, but it’s difficult to press without accidentally rotating it at the same time.  I’ll never figure out why the CLIQ’s designers decided to hide the d-pad under the screen, though.  It’s really a pain to have to slide the keyboard out and rotate the screen just to get access to it.  One major score for the G1.
  • UI – G1
    • Phone manufacturers can never leave an operating system alone.  Imagine if Windows were customized so that it worked completely differently on a Sony than on an HP. Luckily, Motorola didn’t go as far as others (like Samsung).  Still, the stock Android OS looks much better than Motorola’s.
  • OS – G1
    • Here, too, Motorola’s decision to customize Android is a problem.  HTC can update Android on the G1 by adding device-specific code.  For a CLIQ update, Motorola has to merge the entire Android codebase with their own fork.  This means CLIQ updates lag behind other devices.  The G1 has had Android 1.6 for a while.  The CLIQ is still on 1.5 and won’t be updated until Motorola releases 2.1 for it.  Maybe.
  • Touchability – G1
    • Many users (including me) have had problems with the CLIQ’s capacitive touch screen.  Sometimes it works flawlessly and sometimes it doesn’t.  It’s especially annoying when playing games.
  • Exterior appearance – CLIQ
    • The CLIQ’s bold lines and attractive coloring outshine the boring G1.  I highly recommend the titanium white version.
  • Sturdiness – CLIQ
    • With a more solid construction and a responsive slider mechanism, the CLIQ feels much better in the hand.
Posted in Android at December 22nd, 2009. 7 Comments.

Guice BlazeDS’ MessageBroker

In a previous post (http://www.connorgarvey.com/blog/?p=132), I wrote about how to use Guice injection for Flex services.  I used web.xml to configure the MessageBrokerServlet and configured each Flex service to use Guice as a factory.  Since then, on this project, we’ve had to introduce new servlets.  Rather than continue to use web.xml’s verbose and fully-qualified-path based configuration, we moved to using Guice’s ServletModule class.  Here are the steps we followed.

  1. Ensure the guice-servlet.jar is included in your project and is deployed with your build.
  2. Add the Guice filter to web.xml.
    <filter>
      <filter-name>guiceFilter</filter-name>
      <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>guiceFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
  3. Create a servlet module, a class extending com.google.inject.servlet.ServletModule.
  4. Override the configureServlets() method of ServletModule and add the message broker servlet configuration.
    this.bind(MessageBrokerServlet.class).in(Scopes.SINGLETON);
    final Map<String, String> params = new TreeMap<String, String>();
    params.put("services.configuration.file", this.context
        .getRealPath("WEB-INF/config/flex/services-config.xml"));
    this.serve("/messagebroker/*").with(MessageBrokerServlet.class, params);

    1. Normally, servlets configured in Guice are tagged with @Singleton.  Since the MessageBrokerServlet is third party, it’s marked as a singleton here, in the module.
  5. Add the new module to the Guice servlet context listener, which should already be configured in web.xml.
  6. Remove the servlet and servlet-mapping from web.xml.
Posted in Guice at October 20th, 2009. 3 Comments.

Using Guice with Flex remoting for BlazeDS

I just finished putting a server together that uses Google’s Guice and Adobe’s BlazeDS.  Here’s how you can quickly get a project working using the same configuration.

* Update: A new post describes using Guice’s ServletModule to configure the MessageBrokerServlet.

Download the libraries

Download Guice and BlazeDS.  Use the project configured in the BlazeDS war to get started.

Create the Guice factory

Since BlazeDS provides the servlet, you won’t be able to configure your classes using Guice unless you have a Flex factory.  This code will inject itself with Guice to get instances of Flex services.

package com.connorgarvey.guiceblazeds.servlet;
 
import java.util.HashMap;
import java.util.Map;
import com.google.inject.Injector;
import flex.messaging.FactoryInstance;
import flex.messaging.FlexContext;
import flex.messaging.FlexFactory;
import flex.messaging.config.ConfigMap;
import flex.messaging.services.ServiceException;
 
/**
 * <p>A Flex factory that retrieves instances of Flex services from Guice</p>
 * <p>This is based on a similar factory built for Spring by Jeff Vroom</p>
 * @author Connor Garvey
 * @created May 27, 2009 1:09:49 PM
 * @version 1.0.0
 * @since 1.0.0
 */
public class GuiceFactory implements FlexFactory {
  private static final String SOURCE = "source";
 
  /**
   * @see flex.messaging.FlexFactory#createFactoryInstance(java.lang.String, flex.messaging.config.ConfigMap)
   */
  public FactoryInstance createFactoryInstance(final String id, final ConfigMap properties) {
    final GuiceFactoryInstance instance = new GuiceFactoryInstance(this, id, properties);
    instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));
    return instance;
  }
 
  /**
   * @see flex.messaging.FlexConfigurable#initialize(java.lang.String, flex.messaging.config.ConfigMap)
   */
  public void initialize(final String id, final ConfigMap configMap) {
  }
 
  /**
   * @see flex.messaging.FlexFactory#lookup(flex.messaging.FactoryInstance)
   */
  public Object lookup(final FactoryInstance inst) {
    return inst.lookup();
  }
 
  static class GuiceFactoryInstance extends FactoryInstance {
    private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
    GuiceFactoryInstance(final GuiceFactory factory, final String id, final ConfigMap properties) {
      super(factory, id, properties);
    }
 
    @Override
    public Object lookup() {
      final Injector injector = (Injector)FlexContext.getServletContext().getAttribute(
          GuiceServletContextListener.KEY);
      injector.injectMembers(this);
      String className = this.getSource();
      Class<?> clazz = this.classes.get(className);
      if (clazz == null) {
        try {
          clazz = Class.forName(this.getSource());
          this.classes.put(className, clazz);
        }
        catch (ClassNotFoundException ex) {
          ServiceException throwing = new ServiceException();
          throwing.setMessage("Could not find remote service class '" + this.getSource() + "'");
          throwing.setRootCause(ex);
          throwing.setCode("Server.Processing");
          throw throwing;
        }
      }
      return injector.getInstance(clazz);
    }
 
    @Override
    public String toString() {
      return "Guice factory <id='" + this.getId() + "',source='" + this.getSource() +
          "',scope='" + this.getScope() + "'>";
    }
  }
}

Create a context listener

The Guice servlet jar contains a ServletContextListener, but I haven’t taken the time to integrate it into this solution.  For simplicity, you can use this one, which works with the factory above.

package com.connorgarvey.guiceblazeds.servlet;
 
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
 
/**
 * Prepares Guice on application startup
 * @author Connor Garvey
 * @created May 27, 2009 8:37:26 AM
 * @version 1.0.0
 * @since 1.0.0
 */
public abstract class GuiceServletContextListener implements ServletContextListener {
  /**
   * The key of the servlet context attribute holding the injector
   */
  public static final String KEY = Injector.class.getName();
 
  /**
   * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
   */
  public void contextDestroyed(final ServletContextEvent servletContextEvent) {
    servletContextEvent.getServletContext().removeAttribute(KEY);
  }
 
  /**
   * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
   */
  public void contextInitialized(final ServletContextEvent servletContextEvent) {
    servletContextEvent.getServletContext().setAttribute(KEY,
        this.getInjector(servletContextEvent.getServletContext()));
  }
 
  private Injector getInjector(final ServletContext servletContext) {
    return Guice.createInjector(this.getModules());
  }
 
  /**
   * Gets the modules used by the application
   * @return the modules
   */
  protected abstract List<? extends Module> getModules();
}

Extend GuiceContextListener

Create a concret version of the class above.  It should return all modules needed for the application.

Modify web.xml

Now, prepare web.xml with the normal BlazeDS settings plus some extras for Guice.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <display-name>Guice BlazeDS</display-name>
  <description>Guice BlazeDS</description>
  <listener>
    <listener-class>flex.messaging.HttpFlexSession</listener-class>
  </listener>
  <listener>
    <listener-class>com.connorgarvey.guiceblazeds.servlet.MyCustomGuiceServletContextListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>MessageBrokerServlet</servlet-name>
    <display-name>MessageBrokerServlet</display-name>
    <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
    <init-param>
      <param-name>services.configuration.file</param-name>
      <param-value>/WEB-INF/config/flex/services-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>MessageBrokerServlet</servlet-name>
    <url-pattern>/messagebroker/*</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
</web-app>

This way, BlazeDS will start at server startup, followed by Guice.

Modify BlazeDS config

Open services-config.xml and add this at the top of the file.  Point it to the Guice factory.

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
  <factories>
    <factory id="guice" class="com.connorgarvey.guiceblazeds.servlet.GuiceFactory" />
  </factories>

Set the factory of all remoting destinations

In remoting-config.xml, be sure to set the factory of all destinations to the name specified in services-config.xml above.

<destination id="SomeService">
  <properties>
    <factory>guice</factory>
    <source>com.connorgarvey.guiceblazeds.service.flex.SomeFlexService</source>
  </properties>
</destination>

How this all works

  1. When the server starts, BlazeDS and Guice are initialized by the servlet listeners.
  2. When BlazeDS receives a request, to a service, it’ll see that it’s supposed to retrieve it from the “guice” factory.
  3. The Guice factory will return an instance of the class specified in the source of the service configuration from Guice to BlazeDS for use in completing the request.
Posted in Guice at June 19th, 2009. 1 Comment.

Testing in Android with mock UI components

As described in an earlier post, Android is not friendly to mocking frameworks or mock-style testing.  If you want to test any class in your application that deals with the Android API, it’s best to run your tests through the emulator, accessing real Android classes.  It’s unfortunate because you’re not just testing your application.  You’re also testing Android.  Anyway, here’s a way to mock a UI component.

If you’re just starting, here are a couple notes to keep you on the right track.

  • Android is bundled with JUnit 3.  Don’t try using an updated JUnit library or another testing framework.  The Android jar doesn’t contain any functional code, so all test cases have to be run in the emulator, which uses JUnit 3.  The test framework that will work best is in the Android API.
  • If you need basic implementations of Android classes, try to avoid mocking them.

“Mock”ing

In my latest test, I needed a TextView so that I could call the simplest method, setText(String).  I’ll describe how I got one.

Don’t bother with the android.test.mock package.  It just contains implementations of classes that throw UnsupportedOperationExceptions.  There isn’t anything there that I have yet found useful.

  1. In the test case, instead of extending TestCase, extend at InstrumentationTestCase or, if necessary, one of its subclasses.  It’ll set up most of the stuff that’s available in an Activity and make it available to your test case.
    public class AnAndroidTest extends InstrumentationTestCase {
  2. Create a mock implementation of TextView or the class you need.
    public class MockTextView extends TextView {
      public MockTextView(final Context context) {
        super(context);
      }
    }
  3. The TextView constructor needs a real Context object because it will call methods on it.  The context is difficult to mock because parts of it are private to Android.  Since the Android JAR is just an API and doesn’t have any functional code, you couldn’t even see the methods if you tried.  They only exist in the VM in the emulator.  AFAIK, if you can’t see a method, you can’t mock it.  That’s why your test case extends InstrumentationTestCase.  Put this in it.
    final TextView textView = new MockTextView(this.getInstrumentation().getContext());

Now write the test case.  The text view is real and has a fully functional context, so the emulator will have everything it needs to support your test case.

Posted in Android at June 1st, 2009. 1 Comment.

Mocking classes in Android with JMock, JMockIt or EasyMock

* I stand corrected.  A commenter, Kiran Gunda, says it’s possible to mock f inal methods with JMockIt.  I may have set the mock up incorrectly.  If I try again, I’ll update this post.  Until then, an updated post describes how I used Android test classes to run my code.  Matt also pointed out that JMock can mock final methods using JDave’s unfinalizer.

* Updated July 11, 2009 to remove some incorrect information

So that you don’t have to read this whole post, I’ll sumarize what I discovered.  If you’re thinking about using a mocking library to mock Android classes, don’t.  Android uses interfaces sparsely.  That makes a clean API with lots of reusable code, but makes mocking difficult.  The real problem, though, is caused by Android’s generous use of final methods.  I don’t know of any mocking library that can mock final methods, so you just can’t do it.  Instead of writing mocks, look into the android.test and android.test.mock packages.

I developed GreenMileage so that I could learn about the Android OS.  Now that I have an understanding of it, I decided to go back and write test cases so that I could continue development using TDD.  I started by writing tests for utility classes.  That wasn’t a problem.  After finishing that, I moved to some simple UI cases.  The first was TextViewCallbackListener.  I just had to mock TextView.setText(String).

First, I spent hours just trying to get the JMock jars into the project.  For some reason, the compiler would not put JMock into the APK.  I didn’t get any error message or notification.  It just wasn’t there.

I decided to use Android’s test mocks to run my code.  Click here to see a simple example.

Posted in Android at May 30th, 2009. 3 Comments.

Android application Green Mileage open sourced

Green Mileage is now an open source application at Google Code.  You can find the full source for most of the Android posts on this site in it at http://code.google.com/p/greenmileage/.  Just click the Source tab, then the Browse link.

The code needs a lot of cleanup, but is still probably worth a look if you’re new to Android.

Posted in Android at April 27th, 2009. No Comments.

Creating JavaFX sequences from Java code

Scroll down for the full source.  Today, to execute code asynchronously in JavaFX, the background code must be written in Java.  Ideally, your Java code will return JavaFX data types, keeping your FX code clean and helping you be prepared for the day when you won’t need Java.

This is how you can create and return JavaFX sequences from your Java code.

Set the return type of your method to com.sun.javafx.runtime.sequence.Sequence.  Many of the com.sun.javafx classes seem to have been created for use in Java code.

@Override
public Sequence<String> call() throws Exception {

In your code, use any type of collection class you like.  It’s easiest to use List classes, though, because they can be directly converted.

List<String> names = Arrays.asList("Arthur", "Trillian", "Zaphod");

Then, convert the list to a sequence using com.sun.javafx.runtime.sequence.Sequences and return it.

return Sequences.make(TypeInfo.getTypeInfo(String.class), names);

Here it is all together for impatient people like me.

@Override
public Sequence<String> call() {
  List names = Arrays.asList("Arthur", "Trillian", "Zaphod");
  return Sequences.make(TypeInfo.getTypeInfo(String.class), names);
}
Posted in JavaFX at March 21st, 2009. No Comments.

Simple JavaFX Spinner Using a Timeline

I’ve been working on a demonstration JavaFX application.  It was originaly written for the prerelease candidate.  I just updated it to work with JavaFX version 1.1 and thought I’d share it.  This is a simple spinner that can be stopped and started.  Here’s the full source.  A description of how it works is below.

package org.mediabrowser;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.Node;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;

/**
 * A spinning icon, indicating the application is working
 * @author Connor Garvey
 * @created Oct 22, 2008, 8:12:48 PM
 * @version 0.0.2
 * @since 0.0.1
 */

public class Spinner extends CustomNode {
  var rotation: Number = 0;
  var timeline: Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE;
    keyFrames: [
      KeyFrame {
        time: 50ms
        action: tick
      }
    ]
  };

  public override function create(): Node {
    return Group {
      content: [
        ImageView {
          image: Image {
            url: "{__DIR__}resources/color_wheel.png"
          }
          transforms: Rotate {
            pivotX: 8
            pivotY: 8
            angle: bind this.rotation
          }
          translateX: 3
          translateY: 3
        },
        Rectangle {
          width: 22
          height: 22
        }
      ]
    };
  }

  public function start() {
    this.timeline.play();
  }

  public function stop() {
    this.timeline.stop();
  }

  function tick() {
    this.rotation += 20;
    if (this.rotation == 360) {
      this.rotation = 0;
    }
  }
}
  • First, the spinner extends CustomNode. That way, it can be placed anywhere in a UI.
  • The timeline is used to rotate the spinner
    • Since the application will be starting and stopping the spinner, set it to run forever, Timeline.INDEFINITE
    • The spinner only does one thing, turn, so it only needs one key frame.  It’s set to turn 20 degrees every 50ms.
  • JavaFX will call create() to create instances of the spinner
    • The __DIR__ makes the spinner image relative to the current class
    • Since the image is 16×16, set the rotation pivot point to 8×8, the center of the image
    • The angle of rotation is bound to a property of the class so that it can be easily modified
    • When an image starts to rotate, it appears to shake because it’s not round.  To smooth the rotation out, it’s transformed down and to the right and placed inside of a rectangle.
Posted in JavaFX at March 14th, 2009. No Comments.