iPhone App on the way

I finished my first iPhone App last night, it’s nothing overly exciting, in fact it’s a glorified calculator at best; but it’s going to help me familiarise myself with the App Store submission process and how iAds work. But it should also be genuinely useful to Australian drivers, and if it gets a decent number of downloads I’ve already got some planned extra functionality.

I might also extend the App to be useful to drivers in other countries and use it to test internationalised App Store Apps.

Hopefully one of my next posts will have a link to the finished product in the App Store =D

Migrating a local Jira instance to Atlassian OnDemand

Earlier this week I had to migrate a Jira instance from a locally hosted server to Atlassian OnDemand, all and all I have to say it was a surprisingly easy and almost pleasant experience – none the less, I decided to write about the steps I took to do the migration for those of you about to embark on this process.

1. Disable all users on local Jira instance and email team

Chances are if you’re using Jira, you’re part of a Software Team. To prevent any disparities between your Jira instances you need to prevent anybody from logging bugs or progressing them through the workflow until you’re done with your migration.

There’s a few ways to do this, but I think the easiest by far is to remove all groups from Jira Users by going to [Administration] -> [Users] -> [Global Preferences] and then delete all groups from Jira users. Note that Jira Administrators will still be able to login, you should remove the ‘admin’ group and leave the ‘jira-system-administrators’. Remember to re-add all the groups you’ve removed on your OnDemand instance when your migration is complete or your users won’t be able to login.

You might also want to send out an email letting your team know Jira will be down for a specified period of time.

If you really want to, you can setup a “read only” group and setup a Permission Scheme which you’ll use on all your projects to allow “read only” access to your Jira instance while you complete the migration. But given the small amount of time it will take to do an average migration, I wouldn’t suggest it unless you have a really big team working on really mission critical stuff or you have reason to believe your migration will take some time.

2. Export XML Backup file from local Jira Instance

To do this you’ll need to be logged in as a Jira System Administrator.  By default you should have a System Admin called ‘admin’.

After logging in, get to [Administration] -> [System] -> [Import & Export...] -> [Backup System]

You’ll need to specify the filename for your backup file and click [Backup]. The page will tell you where your backup will be stored, which is in the directory ‘export’ in your JIRA_HOME.

Your XML backup file will be archived in zip format.

3. Backup attachments directory from local Jira instance

Exporting the XML above will copy most of your Jira settings including issues, various schemes, users, groups etc. but you need to export files associated with your Jira instance manually. This includes issue attachments (log files, screenshots, etc), logos (in the case you’ve customised the LAF of your Jira instance) and avatars.

Once you’ve copied all the files you need to zip them up ready to be imported by the Atlassian OnDemand ‘JIRA Import’ tool.

You’ll need to put each of these in their own zip file, so if you backup all three directories you should end up with 4 zips, attachments.zip, logos.zip and avatars.zip, plus one that contains the backup XML file obtained in the previous step.

When zipping the files, I preserved the original directory structure, e.g. for the attachments directory ‘data/attachments’ – I’m not sure if this is a requirement, but it’s what worked for me.

4. Copy files to Atlassian OnDemand and import XML Backup

Now you need to get your Jira backup file and any files you backed up on OnDemand.  This is done using a WebDAV client, this is more or less exactly the same as using an FTP client. There are more details on connecting to OnDemand via WebDAV here, but in short you connect to the same address as your OnDemand URL (i.e. <company>.atlassian.net) with your OnDemand username and password.

Once your files are uploaded, you can start the import process: as a Jira System Administrator [Administration] -> [System] -> [JIRA Import] -> [Next]

At this point you’ll be asked to specify the filename of your 4 backup files (only 1 is mandatory), Jira finds these files in your secure OnDemand directory automatically, you just need to tell it which file is which i.e. Attachments -> attachments.zip etc. Click [Next]

5. Finished!

It’s done! Your configuration, issues and accompanying attachments have happily migrated to your new Atlassian OnDemand instance and are ready to start studying for the citizenship test.

The users you disabled back in step 1 will have automatically be added to the ‘users’ group and will automatically have access to Jira with their original auth details, you may want to re-add your original groups to ‘Jira Users’ repeating the process in Step 1 but adding instead of deleting, after you can remove the users group from ‘Jira Users’ if that’s how your previous instance was configured. All that’s left to do is email your team and let them know about the new Jira setup

If you migrated from a locally hosted Jira instance that was on a LAN it might be an idea to make sure your users aren’t simply using the company name or some other easily guessable password to login.

Java’s parseBool() doesn’t really behave how I’d expect

Java’s parseBool() doesn’t really behave how I’d expect

The parseBool() method on Java’s Boolean class returns false in all cases where it doesn’t encounter the string “true”, for example…

public class ParseBool
{
public static void main(String[] args)
{
String strTrue = “true”;
String strFalse = “false”;
String strEmpty = “”;
String strNull = null;
String str1 = “1″;

System.out.println(“strTrue: ” + Boolean.parseBoolean(strTrue));
System.out.println(“strFalse: ” + Boolean.parseBoolean(strFalse));
System.out.println(“strEmpty: ” + Boolean.parseBoolean(strEmpty));
System.out.println(“strNull: ” + Boolean.parseBoolean(strNull));
System.out.println(“str1: ” + Boolean.parseBoolean(str1));
}
}

Running this code gives the output:

true: true
false: false
empty: false
null: false
1: false

The problem here is that a value of null is almost never equal to false. This is especially true in the case of user input, consider a form input “Bill the customer?” with options yes, no or blank/no answer – obviously in a practical situation you would have validation that would force the user to select an option – but in the case that you do not, it makes no sense that blank or null maps to false, blank or null is meaning in itself, it means the field wasn’t filled in, not “no, don’t bill the customer”.

Possible solutions
Personally I think parseBoolean should throw an Exception similar to parseInteger or parseDouble, but that’s not how things are, so to get around this you can:

Check for null

(input==null) ? null : Boolean.parseBool(input);

Create your own parseBoolean

public Boolean tobysParseBool(String input)
{
if(input == null || “”.equals(input)) return null;

return (input.equalsIgnoreCase(“true”)) ? true : false;
}

You could also re-write this method to favour true instead of false as above by changing the last line to:

return (input.equalsIgnoreCase(“false”)) ? false : true;

This way false will only be returned if the input is explicitly false, all other values will be true, though it will usually be safer to check for true and return false for all else.

One simple way to avoid Null Pointer Exceptions doing String comparissons in Java

So you’ve got this code:

String someString = "Some String";

if someString.equals("Some String")
    doSomething();

This is fine because someString is set to the string “Some String”, and doSomething() will be called. If someString was set to “Something else” this would be fine too, because there is a value to compare to. But what if someString was null?

String someString = null;

if someString.equals("Some String")
    doSomething();

someString is not set to an instance of String, it is in fact null, so calling .equals() on null will cause a Null Pointer Exception

The solution is really simple:

if "Some String".equals(someString)
    doSomething();

This way .equals will always be called on what you know is a String, furthermore .equals handles null values. I forget where I first saw this but I’ve always loved what a simple solution it is to the problem. Code robustly and you’ll run into less trouble down the track.

Inaugural First Post

Sup! My name is Toby and this is my brand spanking new blog. It’s not my first, I briefly had one at toby.gundry.com.au but it was hacked; rather than go through the process of restoring everything from scratch I decided to take the opportunity to move to a slightly better domain and redesign the blog from scratch.

I’m a Graduate Software Engineer for a company in Sydney Australia, but I worked for some years as a Web Designer and Developer before that.  I’m interested in, and hopefully WILL write about, Software Engineering & Programming, specifically Mobile and Web App Development, and I’m also very interested in Machine Learning / Data Mining and the use of them in biomedical applications, though my experience in this area is very limited for now.

I’m also interested in product development and innovation as a whole, depending on the day I’m often much more excited about the end product being delivered than I am the technical infrastructure…but that really does depend on the day.

If any of this stuff interests you, then, read me…and if you write about it too then get in touch so I can read you