Why all Java devs should at least consider Groovy and Spock for testing

As a developer, testing is very important. Some developers have the mindset of “Meh, I write code, testing is a QAs job”, which is pretty poor. It’s much better for the developer to be test driving their code, generally if adopted well it produces better quality code, and of course the sooner issues are caught the cheaper they are to address.

Most Java developers who are following TDD probably use mockito or powermock alongside JUnit. I’ve never been much of a fan of those combinations as I believe they involve far too much boilerplate code, and test code often becomes more verbose and harder to maintain than the actual production code itself.

After being introduced to Spock, and testing using Groovy last year, I’m absolutely sold on it and have subsequently used it on several other projects.

For the purpose of this post, I’ll base it around a service class that does some things with a domain object, via a data access layer, which is something most enterprise developers can relate to.

Heres the domain class:

public class User {

    private int id;
    private String name;
    private int age;

    // Accessors omitted
}

Heres the DAO interface:

public interface UserDao {

    public User get(int id);

}

And finally the service:

public class UserService {

    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User findUser(int id){
        return null;
    }
}

Nothing too complex to mention here. The class that we’re going to put under test is the service. You can see that the service is dependant on a UserDao, which is passed into the constructor. This is a good design practice because you’re stating that in order to have a UserService, it must be constructed with a UserDao. This also becomes useful later when using dependency injection frameworks like Spring so you can mark them both as Components and Autowire the constructor arguments in, but alas.

Lets go ahead and create a test class for the service (command+shift+t if using IntelliJ on a mac).

class UserServiceTest extends Specification {

    UserService service
    UserDao dao = Mock(UserDao)

    def setup(){
        service = new UserService(dao)
    }

    def "it gets a user by id"(){
        given:
        def id = 1

        when:
        def result = service.findUser(id)

        then:
        1 * dao.get(id) >> new User(id:id, name:"James", age:27)
        result.id == 1
        result.name == "James"
        result.age == 27
    }
}

Here we go, right in at the deep end, let me explain what is going on here. Firstly, we’re using groovy, so although it looks like Java (I suppose it is in some respects as it compiles down to Java bytecode anyway) the syntax is a bit lighter, such as no semi-colons to terminate statements, no need for public accessor as everything is public by default, Strings for method names. If you want to learn more about groovy, check out their documentation here.

As you can see, the test class extends from spock.lang.Specification, this is a Spock base class and allows us to use the given, when and then blocks in our test.

You’ll see the subject of the test then, the service. I prefer to define this as a field and assign it in the setup, but others prefer to instantiate it in the given block of each test, I suppose this is really just a personal preference.

Creating mocks with Spock is easy, just use Mock(Class). I then pass the mocked DAO dependency into the userService in the setup method. Setup runs before each test is executed( likewise, cleanup() is run after each test completes). This is an excellent pattern for testing as you can mock out all dependencies and define their behaviour, so you’re literally just testing the service class.

A great feature of groovy is that you can use String literals to name your methods, this makes tests much easier to read and work out what it is actually testing rather than naming them as “public void testItGetsAUserById()”

Given, when, then

Spock is a behaviour driven development (BDD) testing framework, which is where it gets the given, when and then patterns from (amongst others). The easiest way I can explain it as follows:

Given some parts, when you do something, then you expect certain things to happen.

It’s probably easier to explain my test. We’re given an id of 1, you can think of this as a variable for the test. The when block is where the test starts, this is the invocation, we’re saying that when we call findUser() on the service passing in an id, we’ll get something back and assign it to the result.

The then block are your assertions, this is where you check the outcomes. The first line in the then block looks a little scary, but actually it’s very simple, lets dissect it.

1 * dao.get(id) >> new User(id:id, name:"James", age:27)

This line is setting an expectation on the mocked dao. We’re saying that we expect 1 (and only 1) invocation on the dao.get() method, that invocation must be passed id (which we defined as 1 earlier). Still with me? Good, we’re half way.

The double chevron “>>” is a spock feature, it means “then return”. So really this line reads as “we expect 1 hit on the mocked dao get(), and when we do, return a new User object”

You can also see that I’m using named parameters in the constructor of the User object, this is another neat little feature of groovy.

The rest of the then block are just assertions on the result object, not really required here as we’re doing a straight passthrough on the dao, but gives an insight as to what you’d normally want to do in more complex examples.

The implementation.

If you run the test, it’ll fail, as we haven’t implemented the service class, so lets go ahead and do that right now, its quite simple, just update the service class to the following:

public class UserService {

    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User findUser(int id){
        return userDao.get(id);
    }
}

Run the test again, it should pass this time.

Stepping it up

That was a reasonably simple example, lets look at creating some users. Add the following into the UserService:

public void createUser(User user){
        // check name

        // if exists, throw exception

        // if !exists, create user
    }

Then add these methods into the UserDao

public User findByName(String name);
    public void createUser(User user);

Then start with this test

def "it saves a new user"(){
        given:
        def user = new User(id: 1, name: 'James', age:27)

        when:
        service.createUser(user)

        then:
        1 * dao.findByName(user.name) >> null

        then:
        1 * dao.createUser(user)
    }

This time, we’re testing the createUser() method on the service, you’ll notice that there is nothing returned this time.

You may be asking “why are there 2 then blocks?”, if you group everything into a single then block, Spock just asserts that they all happen, it doesn’t care about ordering. If you want ordering on assertions then you need to split into separate then blocks, spock then asserts them in order. In our case, we want to firstly find by user name to see if it exists, THEN we want to create it.

Run the test, it should fail. Implement with the following and it’ll pass

    public void createUser(User user){
        User existing = userDao.findByName(user.getName());

        if(existing == null){
            userDao.createUser(user);
        }
    }

Thats great for scenarios where the user doesn’t already exist, but what if it does? Lets write so co…NO! Test first!

    def "it fails to create a user because one already exists with that name"(){
        given:
        def user = new User(id: 1, name: 'James', age:27)

        when:
        service.createUser(user)

        then:
        1 * dao.findByName(user.name) >> user

        then:
        0 * dao.createUser(user)

        then:
        def exception = thrown(RuntimeException)
        exception.message == "User with name ${user.name} already exists!"
    }

This time, when we call findByName, we want to return an existing user. Then we want 0 interactions with the createUser() mocked method.

The third then block grabs hold of the thrown exception by calling thrown() and asserts the message. Note that groovy has a neat feature called GStrings that allow you to put arguments inside quoted strings.

Run the test, it will fail. Implement with the following at it’ll pass.

public void createUser(User user){
        User existing = userDao.findByName(user.getName());

        if(existing == null){
            userDao.createUser(user);
        } else{
            throw new RuntimeException(String.format("User with name %s already exists!", user.getName()));
        }
    }

I’ll leave it there, that should give you a brief intro to Spock, there is far more that you can do with it, this is just a basic example.

Snippets of wisdom

  • Read the spock documentation!
  • You can name spock blocks such as given:”Some variables”, this is useful if its not entirely clear what your test is doing.
  • You can use _ * mock.method() when you don’t care how many times a mock is invoked.
  • You can use underscores to wildcard methods and classes in the then block, such as 0 * mock._ to indicate you expect no other calls on the mock, or 0 * _._ to indicate no calls on anything.
  • I often write the given, when and then blocks, but then I start from the when block and work outwards, sounds like an odd approach but I find it easier to work from the invocation then work out what I need (given) and then what happens(then).
  • The expect block is useful for testing simpler methods that don’t require asserting on mocks.
  • You can wildcard arguments in the then block if you don’t care what gets passed into mocks.
  • Embrace groovy closures! They can be you’re best friend in assertions!
  • You can override setupSpec and cleanupSpec if you want things to run only once for the entire spec.

Conclusion

Having used Spock (and groovy for testing) on various work and hobby projects I must admit I’ve become quite a fan. Test code is there to be an aid to the developer, not a hinderance. I find that groovy has many shortcuts (collections API to name but a few!) that make writing test code much nicer.

Check out the Github Gist here

A few little tweaks to automate Android instrumentation testing via Robotium & Maven

Having recently revived an android project I haven’t opened in close to 6 months, I was left scratching my head as to why I couldn’t run any of my integration tests.

Thinking back, I remembered having problems getting robotium to instrument the clicking of a button, as simple as it sounds, theres a few little gotchas involved. Firstly, I needed to modify the test code to click on text, rather than a button, as it has been suggested by various users on StackOverflow that there does tend to be odd side effects when clicking buttons:

public void testClickGetSurveyTakesToSurveyRunner() {
 solo.clickOnText("Get Survey");
 solo.assertCurrentActivity("Current activity was not correct", SurveyRunner.class);
 }

Next, I needed to add this into the test projects AndroidManifest

<uses-sdk android:targetSdkVersion="10" />

And then to add this into the main projects AndroidManifest:

<supports-screens android:anyDensity="true"/> 

Both of these tweaks are mentioned on the Robotium FAQ, so it might be worth glancing there to see if any enhancements get made in the future

After making those changes, I stumbled into another error that reared its ugly head in the logcat:

ERROR/AndroidRuntime(1185): FATAL EXCEPTION: main
 java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
 at com.roosearch.android.activity.SurveyRunner.onResume(SurveyRunner.java:38)
 at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150)
 at android.app.Activity.performResume(Activity.java:3832)
 at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110)
 at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
 at android.app.ActivityThread.access$1500(ActivityThread.java:117)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:130)
 at android.app.ActivityThread.main(ActivityThread.java:3683)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:507)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
 at dalvik.system.NativeStart.main(Native Method)

There seems to be a rather peculiar requirement, that any dependencies your using on your main application, also need to be in the test projects pom.xml, but marked with a scope of provided. After making that change as advised here and rebuilding, both the app and instrumentation app build and test successfully.

I was also pleasantly surprised that I could run the instrumentation tests via IntelliJ IDEA 12 Ultimate, last time I tried that (on an older version albeit), it wasn’t so simple…

Deploying artefacts into your CloudBees maven repositories.

If you’re like me, and have a fair few hobby projects on the go at any one time, you’re may want to take advantage of some of the free cloud services that are available out there. I’m particulary fond of the Maven repositories that CloudBees offer, as it gives you a safe and easy way to deploy your artefacts, whether they’re 3rd party libraries, snapshots, or even releases of your own software.

Head over to CloudBees.com and register an account, its free.

I’ve recently been doing a fair bit of work 3rd party libraries that are not available on the maven repositories, you have to download the source and compile it yourself (I have another post about an example of that). Since I often develop on different machines, and I’m not actually changing the library, I wanted a single place where I could upload a pre compiled copy of it and just depend on it as I would any other library, such as JUnit.

The first task, is to get your project compiling and working locally, once that is done you can then add the following into your pom.xml

Repository (that references a configured repository on ~/.m2/settings.xml)

<repository>
            <id>cloudbees-private-snapshot-repository</id>
            <name>cloudbees-private-snapshot-repository</name>
            <url>dav:https://repository-jameselsey.forge.cloudbees.com/snapshot/</url>
        </repository>

Also, since maven 3 requires the webdav extension, you’ll need to add this into the build/extensions section of your pom.xml:

<extensions>
            <!-- Extension required to deploy a snapshot or a release to the CloudBees remote maven repository using Webdav -->
            <extension>
                <groupId>org.apache.maven.wagon</groupId>
                <artifactId>wagon-webdav</artifactId>
                <version>1.0-beta-2</version>
            </extension>
        </extensions>

After that, make sure that your ~/.m2/settings.xml file contains details of your CloudBees repositories, here is my copy, make sure you put your password in, and replace occurences of “jameselsey” with your own user ID.

<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
    <server>
        <id>cloudbees-private-snapshot-repository</id>
        <username>jameselsey</username>
        <password>YOUR_PASSWORD_HERE</password>
        <filePermissions>664</filePermissions>
        <directoryPermissions>775</directoryPermissions>
    </server>
    <server>
        <id>cloudbees-private-release-repository</id>
        <username>jameselsey</username>
        <password>YOUR_PASSWORD_HERE</password>
        <filePermissions>664</filePermissions>
        <directoryPermissions>775</directoryPermissions>
    </server>
    <server>
        <id>cloudbees-private-snapshot-plugin-repository</id>
        <username>jameselsey</username>
        <password>YOUR_PASSWORD_HERE</password>
        <filePermissions>664</filePermissions>
        <directoryPermissions>775</directoryPermissions>
    </server>
    <server>
        <id>cloudbees-private-release-plugin-repository</id>
        <username>jameselsey</username>
        <password>YOUR_PASSWORD_HERE</password>
        <filePermissions>664</filePermissions>
        <directoryPermissions>775</directoryPermissions>
    </server>
</servers>
<profiles>
    <profile>
        <id>cloudbees.private.release.repository</id>
        <activation>
            <property>
                <name>!cloudbees.private.release.repository.off</name>
            </property>
        </activation>
        <repositories>
            <repository>
                <id>cloudbees-private-release-repository</id>
                <url>https://repository-jameselsey.forge.cloudbees.com/release</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
    </profile>
    <profile>
        <id>cloudbees.private.snapshot.repository</id>
        <activation>
            <property>
                <name>!cloudbees.private.snapshot.repository.off</name>
            </property>
        </activation>
        <repositories>
            <repository>
                <id>cloudbees-private-snapshot-repository</id>
                <url>https://repository-jameselsey.forge.cloudbees.com/snapshot</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
    </profile>
    <profile>
        <id>cloudbees.private.release.plugin.repository</id>
        <activation>
            <property>
                <name>!cloudbees.private.release.plugin.repository.off</name>
            </property>
        </activation>
        <pluginRepositories>
            <pluginRepository>
                <id>cloudbees-private-release-plugin-repository</id>
                <url>https://repository-jameselsey.forge.cloudbees.com/release</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    </profile>
    <profile>
        <id>cloudbees.private.snapshot.plugin.repository</id>
        <activation>
            <property>
                <name>!cloudbees.private.snapshot.plugin.repository.off</name>
            </property>
        </activation>
        <pluginRepositories>
            <pluginRepository>
                <id>cloudbees-private-snapshot-plugin-repository</id>
                <url>https://repository-jameselsey.forge.cloudbees.com/snapshot</url>
                <releases>
                    <enabled>false</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    </profile>
</profiles>
</settings>

Now, if you run mvn clean install deploy:deploy, maven will create a clean build of your application, install it to your local repository, and then deploy it to your CloudBees snapshot repo.

[INFO] --- maven-deploy-plugin:2.7:deploy (default-cli) @ tess-two ---
WAGON_VERSION: 1.0-beta-2
Downloading: dav:https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/maven-metadata.xml
Downloaded: dav:https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/maven-metadata.xml (769 B at 0.7 KB/sec)
Uploading: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/tess-two-0.0.1-20120720.120205-2.apklib
Uploaded: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/tess-two-0.0.1-20120720.120205-2.apklib (5865 KB at 449.0 KB/sec)
Uploading: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/tess-two-0.0.1-20120720.120205-2.pom
Uploaded: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/tess-two-0.0.1-20120720.120205-2.pom (3 KB at 1.2 KB/sec)
Downloading: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/maven-metadata.xml
Downloaded: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/maven-metadata.xml (276 B at 0.6 KB/sec)
Uploading: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/maven-metadata.xml
Uploaded: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/0.0.1-SNAPSHOT/maven-metadata.xml (769 B at 0.4 KB/sec)
Uploading: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/maven-metadata.xml
Uploaded: https://repository-jameselsey.forge.cloudbees.com/snapshot/tess-two/tess-two/maven-metadata.xml (276 B at 0.2 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 49.874s
[INFO] Finished at: Fri Jul 20 13:02:24 BST 2012
[INFO] Final Memory: 16M/81M
[INFO] ------------------------------------------------------------------------

The same should work for releases, just alter the repository in the pom to point to the releases repo. This isn’t particularly CloudBees specific either, it should work on any remote maven repository, I just like CloudBees, and no, I don’t work for them :P

Any comments/suggestions, please shout!

Asserting for a Toast message using Robolectric

I’ve recently put together a few proof of concept applications, and since they’re “rough and ready” applications, a lot of the functionality is actually mocked, or given a stubbed implementation.

For example, I’ve got various buttons for things like “sign in with LinkedIn” or “Connect with Facebook”. Since its just a proof of concept, and those features aren’t really must haves, I stub them with a Toast message saying something along the lines of “feature not yet implemented”.

This gives the user the opinion that the buttons are there, functional, however the actions they take are not yet implemented.

This is fine, however if you have numerous stubbed toast messages across the application, or even real toast messages that you have in production standard code, you’ll want to unit test those to be sure you don’t introduce defects when you’re busy beavering away in other areas of the source code.

Fortunately we can use the Robolectric framework to cover a lot of these unit tests. I won’t go into detail about Robolectric here, so please head over to their site and have a look at the basics before you can understand this post.

The assertion is pretty straight forward, and consists of the following :

@Test
public void assertValidationFailureWithNullInput()
{
	searchEditText.setText(null);
	searchButton.performClick();

	ShadowHandler.idleMainLooper();
	assertThat( ShadowToast.getTextOfLatestToast(), equalTo("Please enter a value."));
}

What I have here, is an EditText that I use for a search button, I set its value to null and then click on it. The purpose of the test is to ensure that submitting “search” with a null input will be caught by my validation, and a toast message prompting the user to enter valid data.

Hope that helps, and if you have any questions please leave a comment :)

A second app to launch; Agile Planning Poker

After launching my first application onto the market back in March 2011, and amassing somewhere in the region of 15,000 downloads since it’s launch, I was eager to produce another.

I offered up my services at my work to develop an application to “test the water”, teaming up with the marketing director we created a simple yet useful application for agile project managers; planning poker decks.

The concept is simple, when an agile team is in an estimation phase, they assess each task and try to estimate how much effort would be involved to complete that task. There are many different approaches to how the estimation can take place, such as grouping tasks into small/medium/large, or even a simple show of hands voting system. Another method is with the use of planning poker cards.

We decided to keep it simple and offer 3 types of estimation, or 3 decks of card in this application; standard, fibonacci, and hours deck, with the following cards :

Standard

  • 0
  • 0.5
  • 1
  • 2
  • 3
  • 5
  • 8
  • 13
  • 20
  • 40
  • 100

Fibonacci

  • 0
  • 1
  • 2
  • 3
  • 5
  • 8
  • 13
  • 21
  • 34
  • 55
  • 89

Hours

  • 0
  • 0.5
  • 1
  • 2
  • 4
  • 8
  • 12
  • 16

In addition to the numbers above, each deck has the following special cards :

  • ? – Played when you genuinely have no idea how long it would take
  • Infinity symbolPlayed when you believe the task would take forever, or at least longer than is feasible
  • Coffee mugPlayed when you’ve just had enough, and need a timeout

The idea is that when estimating tasks, the users would all select the appropriate card, and on call display their selection to the rest of the team. This rules out any obvious biased choices as the users would all select their own cards, and display at the same time ruling out any options for copying the developer next to you.

The idea is to stimulate discussion and justification of the estimates, so if you estimate a task would be 5 days, but Dalibor estimates it’s only a few hours, it opens up a debate and can rule out any obvious misunderstandings or misconceptions about the task itself, or how it could be achieved, eventually resulting in more accurate estimates.

Click here to view/download the application from the market.

If you’re interested in web services, systems integration and other such enterprise technologies, be sure to check out our blog, also have a look at my write up from DroidCon UK 2011, plenty of android goodness lies within.

Automating android application signing and zipaligning with maven

Code rage

This is something that has had me tearing my hair out for a few days now, I was pretty much border-line braveheart-ing my screen….

Code rage

I’ve recently been on a little drive to try to maven-ize my projects. All had been going well until I needed to sign and zipalign my APKs. This post will help you conquer that barrier with the use of some maven plugins.

When using ant, I was able to simply enter keystore details into build.properties and just call “ant release”. Unfortunately that approach doesn’t carry across to maven, and you have to provide some more configuration.

Firstly, before we go any further, I’m going to assume that you already have a maven android project setup, so you have a pom.xml, you’ve configured the maven-android-plugin and you can run “mvn clean install” to build your APK, and “mvn android:deploy” to deploy it to an emulator. If you haven’t got that far, I’d suggest you have a look at one of my previous posts to help get you up to speed.

So, when you want to build your application with maven, you’d run “mvn install”. That will, by default, use a debug key to sign your APK. When we want to build a releasable APK we still want to execute the same install goal, however we’ll want to use a proper key. Luckily, maven provides something called profiles.

In short, maven profiles allow you to still perform the same standard goals, yet they behave slightly different, in the manner of binding extra steps to them, all will come clearer in a moment.

This has already been covered, in a useful post by the guys at Novoda, and various other blog posts scattered around the web. I’ve followed at least 10 tutorials and each time I was unable to get the signing process to work correctly, each time I encountered the following error :

INFO] jarsigner: attempt to rename C:\android-projects\jameselsey_andsam_branch_mavenbranch\target\LanguageSelection-1.0.0-SNAPSHOT.jar to C:\android-projects\jameselsey_ands
am_branch_mavenbranch\target\LanguageSelection-1.0.0-SNAPSHOT.jar.orig failed
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Failed executing 'cmd.exe /X /C "C:\development\tools\Java\jdk1.6.0_20\jre\..\bin\jarsigner.exe -verbose -keystore my-release-key.keystore -storepass '*****' -keypass '
*****' C:\android-projects\jameselsey_andsam_branch_mavenbranch\target\LanguageSelection-1.0.0-SNAPSHOT.jar mykeystore"' - exitcode 1
[INFO] ------------------------------------------------------------------------

I’d tried everything, even copying out the command and pasting into a command window worked, but I could not get it to work from maven. Unfortunately it seems there may be an issue with the maven-jarsigner-plugin (as suggested in the comments on the Novoda post). However fear not, for there is an alternative, the maven-jar-plugin.

The maven-jar-plugin is a similar plugin to the jarsigner plugin, however the signing APIs are now deprecated and it points you to use the (apparently) broken maven-jarsigner-plugin. Using a deprecated API doesn’t particulary concern me in this instance, as its just signing artefacts.

Take a look at my profiles section, copy this into your pom.xml :

<profiles>
<profile><!-- release profile. uses keystore defined in keystore.* properties. signs and zipaligns the app to the target folder-->
            <id>release</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <build>
                <defaultGoal>install</defaultGoal>
                <finalName>${project.artifactId}-${project.version}</finalName>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-jar-plugin</artifactId>
                        <version>2.2</version>
                        <executions>
                            <execution>
                                <id>signing</id>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                                <phase>package</phase>
                                <inherited>true</inherited>

                                <configuration>
                                    <keystore>
                                        my-release-key.keystore
                                    </keystore>
                                    <storepass>mypassword</storepass>
                                    <keypass>mypassword</keypass>
                                    <alias>mykeystore</alias>
                                    <verbose>true</verbose>
                                    <verify>true</verify>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <plugin>
                        <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                        <artifactId>maven-android-plugin</artifactId>
                        <inherited>true</inherited>
                        <configuration>
                            <sign>
                                <debug>false</debug>
                            </sign>
                        </configuration>
                    </plugin>

                    <plugin>
                        <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                        <artifactId>maven-android-plugin</artifactId>
                        <configuration>
                            <zipalign>
                                <verbose>true</verbose>
                                <skip>false</skip>
                                <!-- defaults to true -->
                                <inputApk>${project.build.directory}/${project.artifactId}-${project.version}.apk</inputApk>
                                <outputApk>${project.build.directory}/${project.artifactId}-${project.version}-RELEASE.apk
                                </outputApk>
                            </zipalign>

                        </configuration>
                        <executions>
                            <execution>
                                <id>zipalign</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>zipalign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
</profiles>

OK, so lets walk through what the above profile does. Firstly, the “id” of the profile is “release”, so when you want to apply this profile, you’d run “mvn install -Prelease”. The “activeByDefault” is set to false, which means you need to use the above arguement, if you flip that over, you won’t need the P flag.

The execution goal is to “sign”, which is the API on the plugin, documented here. We bind this execution on to the standard “package” goal. Then we provide the configuration elements which specify the details of the keystore.

In pure English, this binds the plugin phase onto the package goal of maven, so anytime we run using this profile it’ll execute the jar signing of our artefacts. The “verify” tag gives us extra piece of mind by verifying that the signing was successful afterwards.

I’ve also setup a zipalign profile that will take the APK, zipalign it, and rename it to “*-RELEASE.apk”, so I know that particular APK is the one which I’ll release to market.

So thats it, once more a success, and its just one small step on the ladder to android glory!

Phhew!! Done, finally I was able to shutdown the laptop and go to sleep at 3am….on a school night!!!

Good luck, feel free to comment!

Peace.

Coupling and Cohesion, what you need to know for SCJP…

Coupling and cohesion are two terms that often get mixed up, however they are actually really simple concepts, and the bonus is, they don’t just apply to Java.

Coupling

Coupling, in its purest terms, means “the degree to which one class knows about another class”. If one class uses another class, that is coupling. Coupling is everywhere, but the level of coupling varies.

Consider the following example of a tightly coupled set of classes:

public class TightlyCoupledClass
{
    public static void main(String[] args)
    {
        ExampleClass exampleClass = new ExampleClass();
        exampleClass.message += "James";
        System.out.println(exampleClass.message);
    }
}

class ExampleClass
{
    public String message = "hello ";
}

TightlyCoupledClassuses ExampleClass, therefore there is some coupling. The level of coupling is high as TightlyCoupledClassdirectly alters the message variable on ExampleClass. It’ll compile and run perfectly fine, but if you slip this little nugget into production code, you’re colleagues will bash you for eternity, because its poor design.

Think of it this way, what if ExampleClass was used in hundreds of classes, or what if ExampleClass was maintained by someone else; what would happen if they decide to change the scope of message, or to change its data type? It’ll break anything that uses it, since it is tightly coupled.

From the perspective of TightlyCoupledClass, it needs to get a message, and set a message, it should not care about how ExampleClass maintains that. When a class knows too much about another classes’ implementation, that is also tight coupling.

What we need, is encapsulation, this is another OO concept that shields a classes state and exposes it with accessor methods, meaning that a class can still be coupled, but loosely.

You should, be aiming for loosely coupled classes, lets re-visit the above sample but this time we’ll move from a tightly coupled set of classes, to a loosely coupled set of classes, using encapsulation.

public class TightlyCoupledClass
{
    public static void main(String[] args)
    {
        ExampleClass exampleClass = new ExampleClass();
        String ourUpdatedMessage = exampleClass.getMessage() + "James";
        exampleClass.setMessage(ourUpdatedMessage);
        System.out.println(exampleClass.getMessage());
    }
}

class ExampleClass
{
    private String message = "hello ";

    public String getMessage()
    {
        return message;
    }

    public void setMessage(String message)
    {
        this.message = message;
    }
}

Cohesion

Cohesion is another OO concept like coupling, however cohesion refers to the degree in which a class has a single, well defined purpose. If you had a class called Car, it would maintain state such as numberOfWindows, numberOfWheels, and have behaviour (methods) such as drive(), brake(), stop() etc. That would indicate that the class is cohesive, meaning that it serves a single, defined purpose.

Now, exploring a little, if the Car class suddenly decided to have methods such as switchOnTheTV(), or hangTheWashingOut(), then its not really doing Car-like behaviour. If a class is trying to do more than one thing, it is considered a low cohesive class.

Consider the following, highly cohesive class

package ooconcepts;

public class Car
{
    private String make = "Aston Martin";
    private int numberOfWindows = 5;
    
    public void drive()
    {
        // do some driving!
    }
    
    public void brake()
    {
        // slow down!
    }
    
    public void stop()
    {
        // STOP!!!!
    }      
}

Conclusion

These are the important bullet points to take away from this page:

  • Coupling refers to the degree in which one class knows about another, or makes use of another classes’ members
  • Loose coupling is GOOD as classes are well encapsulated to minimise references to each other
  • Tight coupling is BAD because a class shouldn’t know about the workings of another
  • Cohesion refers to the degree in which a class has a single, well defined purpose
  • High cohesion is GOOD as a class does only what it should
  • Low cohesion is BAD because a class is trying to solve everything and not just its specific purposes

Further Reading

  1. Why couplig is always bad
  2. Java Boutique

Android; Continuous integration, all made lovely with Maven

Lets face it, the eclipse ADT plugin is great for getting an android application up and running quickly, but if you want an easier way to get libraries, and a continuous intergration environment for robust automated testing and building, then maven is the way to go.

IntelliJ have recently released the Early Access Program to their version X of IDEA, this comes with Android support in the community edition, meaning we’re no longer bound to using eclipse for Android development!

The first thing you want to do, is to run through the “create new project” wizard in IntelliJ, its fairly straightforward, just run through and setup a simple android applicaiton. When you’ve got that, run it up on the emulator just to make sure any autogenerated code IntelliJ created works OK.

OK so now we’re ready to start gutting it out and providing the Maven framework. First thing you need to do, in the root directory of the android project, create a file called pom.xml with the following contents

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>MavenMess</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>apk</packaging>
    <name>Maven Android Plugin - samples</name>

    <dependencies>
        <dependency>
            <groupId>com.google.android</groupId>
            <artifactId>android</artifactId>
            <version>2.2.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                <artifactId>maven-android-plugin</artifactId>
                <version>2.6.0</version>
                <configuration>
                    <sdk>
                        <!--  platform or api level (api level 4 = platform 1.6)-->
                        <platform>8</platform>
                    </sdk>
                    <emulator>
                        <!--  the name of the avd device to use for starting the emulator-->
                        <avd>GoogleAPIs</avd>
                    </emulator>
                    <deleteConflictingFiles>true</deleteConflictingFiles>
                    <undeployBeforeDeploy>true</undeployBeforeDeploy>
                </configuration>
                <extensions>true</extensions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <!--  version 2.3 defaults to java 1.5, so no further configuration needed-->
                <version>2.3</version>
            </plugin>
        </plugins>
    </build>
</project>

The POM file is what maven uses to build/test your project. If you’re not familiar with maven at this stage I’d suggest a quick browse of their documentation to get to grips with the fundamentals.

The above POM does a couple of tasks, firstly it tells maven to build an APK file using the packaging statement. You need this otherwise maven wouldn’t know what to create, and might create a WAR or EAR file instead.

You declare the android SDK as a provided dependancy. Next comes the build section, this is where the magic happens. The source directory tells maven where it can find all your android source files to compile.

You’ll need to declare usage of the Jayway plugin, this is a neat little plugin that I picked up from Hugo Josefson from Jayway, at DroidCon UK 2010. There is some configuration that you can set here such as the API level and which emulator to deploy the application to. The second plugin is the maven Java compiler, we need this in order to actually compile the class files.

Right so thats your POM sorted, next you can go ahead and delete the following items

  • \bin
  • \libs
  • build.properties
  • build.xml

You won’t need those files/directories, those are used for the autogenerated ant build script that the android IntelliJ plugin creates, and we’re now using maven.

Right thats it for the maven configuration, next comes actually running the application. The maven goal of “mvn install” will compile all your classes, so run that to check the above is OK.

To deploy your application to a device, you can run the maven goal of “mvn android:deploy”. These goals are great, but what about a 1 button click for building and deploying? Easy…

Along the top of IntelliJ, click on the drop down menu for run targets and create a new run/debug configuration. Using the goal of “android:deploy” will deploy the application to the emulator, but you can also setup a goal of “mvn install” which happens before deployment, as shown in the screenshot below. This will build and deploy your application to the emulator with one click.

All you need to do then is to go into your emulator and start your application, simple!

Any questions/suggestions, please let me know!

Big thanks to the guys at Jayway for sharing this, and making it possible.