Forking JUnit tests in Ant (watch out!)

Turtles are surprisingly fast.

Turtles are surprisingly fast.

I’ve noticed for a while our unit tests run very fast through my IDE but take forever on our build box. At first I attributed this to our severely overloaded build box, but I was wrong.

In our particular case the tests take 5 minutes 3 seconds to run through Ant while forking for each test class. Very not cool.

If you’re using fork to run your JUnit tests in Ant, there are two attributes to be concerned with: fork and forkmode.

The forkmode attribute is the big one here. Possible values are “perTest” (default), “perBatch”, and “once”.

It turns out that because “perTest” is the default; meaning forking is done for each test class. While that might be what you want, it can make your tests significantly slower. Using the “once” option instead means forking happens just once; all your tests will be ran together in a single JVM.

After switching the forkmode to “once”, our test running time plummeted to 33 seconds for a net gain of 4.5 minutes. As Borat would say, “very niiiice”. (In this case 33 seconds is still longer than it should be, but that’s for another post).

There’s some very good technical reasons to run all your tests in the same JVM. As Chris at nominet.org.uk pointed out, it might reveal some issues with your production code or test code:

Having the tests run each in its own JVM also covers up problems. You can create whatever sort of mess you like and it’ll all be swept away before the next test runs. While going through a setting the forkmode to “once” I found a database connection leak in some test code. This sort of problem would be much more visible if all the test code was running in a single JVM and reminded me of Martin Fowler’s advice on testing resource pools.

Of course Martin Fowler comes through again with good advice.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Backing up MySQL Databases with mysqldump

We all know that backing up critical data is very important. Unfortunately, it’s not always very clear how to go about doing that.

Luckily, making back ups of MySQL databases is easy by using mysqldump.

Backing up all databases

Backing up all databases is as easy as as this:

mysqldump -u username -p password –all-databases -c > mysqldump.sql

Did you expect it to be much harder? Sorry to disappoint.

The –all-databases option backs up all databases (genius naming!). The –complete-insert or -c uses complete insert statements in the backup script.

With the above command, mysqldump outputs all the SQL needed to regenerate all databases from scratch with all the data from the time of the dump. Users and other MySQL tables are also included in the dump.

Backing up a specific database or table

Sometimes it’s useful to only backup a small portion of the MySQL instance, either an entire database or a specific set of tables.

Not surprisingly, you can backup a specific database with mysqldump:

mysqldump -u username -p password YourDatabase > yourdatabase.sql

It’s just as easy to backup one or more tables in a database:

mysqldump -u username -p password YourDatabase table1 table2 > yourdatabase.sql

Compressing the backup

If you have a lot of data, compression with gzip will be helpful to eliminate disk space waste:

mysqldump -u username –password=password –all-databases -c | gzip -9 > mysqldump.sql.gz

Automating backups

If you’re dealing with a database of any significant importance, it’s critical to automate the backup process. In the Unix world there is cron. I won’t go into specifics on how to use cron since it is easily worthy of its own posting.

If you ever need your backup, it’ll suck. With backups, it’ll suck less. With automated backups, it’ll suck much much less.

mysqldump isn’t the right tool for all your MySQL backup needs, but its ease of use gives you no excuse. More complicated backup techniques, including incremental backups, can be found in the MySQL reference guide.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

First look at Apple’s App Store ratings system - Your iPhone is safe!

I somehow missed the flurry of Apple news today, so I was surprised to see the updates to iTunes Connect when I wanted to check up on the number of downloads for my first iPhone App Store application (it was approved late last night). I haven’t seen much talk on the Apple’s App Store ratings, so here’s the tiny bit of details that I’ve seen about this new feature.

Before an iPhone developer can update an existing app or upload a new app, they must select the ratings for their own applications:

appstore-content-descriptions

iPhone developers are asked to choose the content frequency (None, Infrequent/Mild, and Frequent/Intense) of various types of objectionable content.

I find it very interesting that developers are being asked to provide these details. Presumably the developers themselves would know about any Hot Coffee-eque features to their apps and fess up, right? I assume the game plan is for the employees already swamped with app approvals will be in charge of validating the accuracy of the developer’s own ratings.

App Store Ratings 4+, 9+, 12+, 17+

App Store Ratings

Apple apple appears to have their very own ratings system:

  • 4+, Applications in this category contain no objectionable material.
  • 9+, Applications in this category may contain mild or infrequent occurrences of cartoon, fantasy or realistic violence, and infrequent or mild mature, suggestive, or horror-themed content which may not be suitable for children under the age of 9.
  • 12+, Applications in this category may also contain infrequent mild language, frequent or intense cartoon, fantasy or realistic violence, and mild or infrequent mature or suggestive themes, and simulated gambling which may not be suitable for children under the age of 12.
  • 17+, Applications in this category may also contain frequent and intense offensive language, frequent and intense cartoon, fantasy or realistic violence, frequent and intense mature, horror, and suggestive themes, plus sexual content, nudity, alcohol, tobacco, and drugs which may not be suitable for children under the age of 17.

Interestingly no application will be sold on the App Store that has “Prolonged graphic or sadistic realistic violence” or “Graphic sexual content and nudity” regardless of the frequency or severity. I guess that means we won’t be seeing any porn anytime soon.

Apple also provides a chart showing the app store rating system’s equivalent to the ESRB and PEGI rating systems:

Are these are equivelent?

Are these are equivelent?

Hopefully this will eliminate the controversy surrounding the rejection of apps due to its objectionable content.

More importantly, I hope the ratings system does not delay the approval process anymore.

Enjoy the new iPhone OS 3.0 upgrade in about a week. Since I’m impatient I might finally grab the version already available to developers. If anything is hosed, I’ll be hosed in a about week anyhow.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Solved: Digester.getParser: org.xml.sax. SAXNotRecognizedException: http://apache.org/xml/features/validation/dynamic

I ran into a nice little problem trying to get richfaces deployed on Oracle’s OC4J:

Digester.getParser:
org.xml.sax.SAXNotRecognizedException: http://apache.org/xml/features/validation/dynamic
	at oracle.xml.jaxp.JXSAXParserFactory.setFeature(JXSAXParserFactory.java:128)
	at org.apache.commons.digester.parser.XercesParser.configureXerces(XercesParser.java:185)
	at org.apache.commons.digester.parser.XercesParser.newSAXParser(XercesParser.java:138)
        ... snip ...

From a little bit of googling, I found several people running into this problem or something very similar. Frustratingly, not a whole lot of solutions. One solution that did not work (but was confirmed by some to do the trick) was to run the OC4J standalone server with the following parameters:

-Dbootclasspath:/somepath/xerces-2.6.2.jar
-Dorg.xml.sax.drive­r=org.apache.xerces.­parsers.SAXParser
-Djavax.xml.parsers­.SAXParserFactory=or­g.apache.xerces.jaxp­.SAXParserFactoryImp­l
-Djavax.xml.parsers­.TransformerFactory=­org.apache.xalan.pro­cessor.TransformerFa­ctoryImpl
-Djavax.xml.transfo­rm.TransformerFactor­y=org.apache.xalan.p­rocessor.Transformer­FactoryImpl

Luckily a co-worker (who is waaaaaaay to humble for his own good and won’t let me use his name here) figured out that adding the following to orion-application.xml does the trick:

<orion-application>

	<imported-shared-libraries>
		<remove-inherited name="oracle.xml"/>
		<remove-inherited name="oracle.xml.security"/>
		<remove-inherited name="oracle.toplink"/>
	</imported-shared-libraries>

</orion-application>

Oracle has details on what the above does in their documentation on utilizing the OC4J class loading framework. Good luck reading that, it looks terribly boring. :-)

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

MediaWiki bot using JWBF (Java)

wiki! wiki!

wiki! wiki!

One of the nice things about Java is there seems to be a friendly (or at least relatively friendly) API for everything.

Java Wiki Bot Framework (JWBF) is a Java framework for working with wikis running MediaWiki (the wiki software used by Wikipedia and all the other Wikimedia Foundation projects).

A little off subject: who thought it was a good idea to name two distinct but related things WikiMedia and MediaWiki? Good luck keeping those terms straight.

Back to JWBF: It is pleasantly easy to use. Admittedly, my needs are far from complex: replace the text of a couple of templates on a regular basis. It’s hardly glamorous programming, but it should save us some time at work. Now we’ll have more time to sing along with
Dr. Horrible’s Sing-Along Blog.
Invent a freeze ray.

Happily the library exists in the central maven repository, so getting it included in my project is easy enough:

    <dependency>
      <groupId>net.sourceforge</groupId>
      <artifactId>jwbf</artifactId>
      <version>1.2-186</version>
      <scope>compile</scope>
    </dependency>

Actually using the framework is as easy as this:

        MediaWikiBot mediaWikiBot =
            new MediaWikiBot( "http://hostname/wiki/" );
        mediaWikiBot.login( "CurrentlyDeployedBot", "password" );
        Article article = new Article(mediaWikiBot.readContent(
            "Template:Currently deployed/Arinc" ), mediaWikiBot );
        article.setText( "Test" );
        article.save();

It’s always nice when things are this easy. *cheers*

One more thing: if you’re looking to create a bot or script for automatic or semi-automatic usage of Wikipedia, please review Wikipedia’s bot policy first.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Saving app data with the iPhone SDK and Cocoa is easy with NSUserDefaults

A quick look at NSUserDefaults suggests saving app data with Cocoa and the iPhone SDK is easy. I haven’t gotten much of a chance to use it so there might be some gotchas.

To store nonsensitive data using NSUserDefaults is as easy as a couple of lines of code:

	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	[defaults setObject:usernameTextField.text forKey:@"username"];
        [defaults synchronize];

The last line is particularly important as it actually saves the data to disk.

Retrieving data is equally as easy:

	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSLog([defaults objectForKey:@"username"]);

NOTE: Using NSUserDefaults is a really bad idea for sensitive data like passwords. A significantly safer solution would be to use the iPhone’s keychain. Apple has an example found in GenericKeychain.

The API can be difficult to understand and cumbersome to use. Luckily, there is a solution for that from Buzz Anderson and it can be found on github.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

SSH warns “it is possible that someone is doing something nasty!”

Let this be a warning to all: SSH knows what you’re doing and SSH is not pleased.

Innuendos aside, I got this nice little error trying to SSH into my brand new server at home. And by “brand new”, I mean it’s my wife’s old desktop that is now running Ubuntu Server 9.04.

  $ ssh myserver
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
  Someone could be eavesdropping on you right now (man-in-the-middle attack)!
  It is also possible that the RSA host key has just been changed.
  The fingerprint for the RSA key sent by the remote host is
  95:00:83:54:de:45:f1:g3:45:34:be:88:98:42:e2:c8.
  Please contact your system administrator.
  Add correct host key in /home/ashlux/.ssh/known_hosts to get rid of this message.
  Offending key in /home/ashlux/.ssh/known_hosts:2
  RSA host key for myserver has changed and you have requested strict checking.
  Host key verification failed

So how did this happen? Basically, I used to have my router setup to forward the SSH port to my computer. Basically my computer at work had the RSA key for my computer, not the new server.

Contrary to the tidbit about requesting “strict checking”, using the -o stricthostkeychecking=no gave the same result.

Luckily the error message gave me one big hint as to how to fix this: “Offending key in /home/ashlux/.ssh/known_hosts:2″. The solution was simple enough, just delete the second line of the known_hosts.

SSH is working again. *cheers*

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

potbs4j 0.4: Java library for Pirates of the Burning Sea web services

Pirates in your Java, sacking the classloader.

Pirates in your Java, sacking the classloader.

A few weeks ago I put together a Twitter publisher for Pirates of the Burning Sea (PotBS) for my wife.  She plays the game perhaps a bit too religiously. :-)  Anyhow, two things get published to twitter: (1) server status changes, and (2) in-game port status changes (who is battling who).

To make life a little easier, I wrote potbs4j, a Java library  to work with PotBS services. (My name for the library is genius, really!)  There really wasn’t any need to couple the twitter publisher with XML parsing and HttpURLConnection.

I doubt ayone will make use of the library, but if anyone is really interested in using it, I’ve worked out some usage instructions here.

If you’re using Maven (highly recommended), just include the potbs4j in your list of dependencies:

<dependency>
<groupId>com.ashlux.potbs</groupId>
<artifactId>potbs4j</artifactId>
<version>0.4</version>
</dependency>

Since potbs4j does not exist in the central repository, you will also need to add my maven repository (it’s slow but works) to your pom.xml:

<repositories>
<repository>
<id>ashlux-repository</id>
<url>http://www.ashlux.com/maven2/repo</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<repository><id>ashlux-snapshot-repository</id>
<url>http://www.ashlux.com/maven2/snapshotRepo</url>
<snapshots>
<enabled>true</enabled>
</snapshots></repository>
</repositories>

You can get the server status with the following code:

ServerStatusService serverStatusService =
new ServerStatusServiceImpl("apikey", "userid");

// get list of all server statuses
ServerListDocument serverListDocument =
serverStatusService.getAllServerStatuses();

// get server status for a single server
ServerDocument serverDocument =
serverStatusService.getServerStatus(ServerName.Antigua);

You can get the server status with the following code:

LandmarkStatusService landmarkStatusService =
new LandmarkStatusServiceImpl("apikey", "userid");
// get list of all port statuses for a server

PortListDocument portListDocument =
landmarkStatusService.getAllLandmarkStatuses(ServerName.Antigua);

// get list of all port statuses for a server
PortListDocument portListDocument =
landmarkStatusService.getLandmarkStatus(ServerName.Antigua, PortName.IRSH_PT);

There are also two utility classes NationUtils (for converting a nation to a nationality) and PortUtils (for converting a PortName.Enum to a string).

An important thing to keep in mind: the library currently does NOT cache results, so you will need to handle this on your own.  Both of the services do implement a method called getMinimumUpdateFrequency that returns the minimum number of minutes you should wait until calling the service.

The source code is hosted on github in all its glory.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

How to: HTTP POST and Google’s ClientLogin using Objective-C and the iPhone SDK

I’ve been working on an iPhone app that uses one of Google’s APIs.  The following appears to work just fine in a non-jailbroke phone.

Creating the request

NSURL *url = [NSURL URLWithString:@"https://www.google.com/accounts/ClientLogin"];
NSMutableURLRequest *loginRequest = [NSMutableURLRequest requestWithURL:url];
[loginRequest setHTTPMethod:@"POST"];</code>

//set headers
[loginRequest addValue:@"Content-Type" forHTTPHeaderField:@"application/x-www-form-urlencoded"];
[loginRequest addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSString *requestBody = [[NSString alloc]

initWithFormat:@"Email=%@&amp;Passwd=%@&amp;service=finance&amp;source=%@",
username, password, [NSString stringWithFormat:@"%@%d", @"ashlux-igFinance-1.0"]];

[loginRequest setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding]];

This part is fairly straight-forward. The service=finance should be changed to the Google service you are using.  Also ashlux-igFinance-1.0 should be changed to the format company-appname-version.

The default timeout interval for the request connection is 60 seconds.  To change this, use setTimeoutInterval:

[loginRequest setTimeoutInterval:30]; // set timeout for 30 seconds
[loginRequest setTimeoutInterval:90]; // set timeout for 90 seconds

Sending the request

To send the request, I am sending a synchronous request (which will block) to Google:


NSHTTPURLResponse *response = NULL;
NSData *responseData = [NSURLConnection sendSynchronousRequest:loginRequest returningResponse:&amp;response error:nil];
NSString *responseDataString = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(@"Response from Google: %@", responseDataString);

Objective-C does have asynchronous IO (non-blocking), but that’s for another time.  For most purposes, asynchronous is the way to go to avoid blocking the application.

Reading the response

For my purposes, I am storing the data in a struct called GoogleClientLogin to represent Google’s ClientLogin data (that’s simple enough, so I will not list it here).  For simplicity, I am not interpreting the response status beyond success (code=200) and failure (code=anything else).


if ([response statusCode] == 200) {
NSLog(@"Login successful.");
GoogleClientLogin *aGoogleClientLogin = [GoogleClientLogin alloc];
aGoogleClientLogin.username = username;
aGoogleClientLogin.password = password;
NSString *authToken = [[responseDataString componentsSeparatedByString:@"Auth="] objectAtIndex:1];
NSLog(@"Google authToken=%@", authToken);
aGoogleClientLogin.authToken = authToken;
return [aGoogleClientLogin autorelease];
} else {
NSLog(@"Login failed.");
return nil;
}

That is more or less all there is to it. There is room for better error handling, but the effort would be better spent elsewhere on the applcation.

Next up, I’ve really need to figure out how to work in unit tests using Xcode.  My previous attempts at getting OCUnit working were full of fail special thanks to Apple’s out-of-date documentation.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Unexpected error 0xE800003A application verification failed

I’ve been spending time lately learning to use Objective-C and the iPhone API.  While trying to deploy a sample iPhone app through Xcode, I ran into a pesky error message.

Your mobile device has encountered an unexpected error (0xE800003A) during the install.

Application verification failed.

Configuring Xcode is a quick and easy two step process (assuming you’ve setup the appropriate certificates, provisioning, etc. with Apple):

  1. Set your bundle identifier in Info.plist (This is your APP ID excluding the Bundle Seed ID).
  2. Set the project code signing identity to your provisioning profile.

That’s it!

Of course, I ran into three different errors when trying to deploy it to my iPhone:

  1. Bundle identifier is incorrect (typo or bundle seed ID was included).
  2. Incorrect provisioning profile was selected.
  3. Clean and rebuild and deploy (Build > Clean All Targets).

The first two problems where easy to resolve, but the third item was definitely tricky.  Who would have thought you’d need to clean the project after making that sort of change?

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis