April 23rd, 2013 | Tags:

A while back I came across a very useful service that I thought could be used for a lot of things. The service that I am talking about is PushBullet developed by redittor /u/guzba. I decided to try and write a small android app that would allow me to share content across devices using this service.

PushBullet has an API that was developed recently and it seemed to work well with

curl https://www.pushbullet.com/api/devices -u API_KEY:

I basically wanted to execute the same thing on my android device. As any Android developer will tell you making HTTP calls from Android isn’t exactly the easiest thing in the world, you have to wrap your call in an AsyncTask and then use the Handler mechanism to update the UI when the call is complete. Luckily, James Smith has wrapped all this up, very neatly, in a android-async-http library that is a breeze to integrate into your project.

The PushBullet API uses Basic HTTP authentication as a security mechanism. This means we must pas our API key as the username to the PushBullet API when we request devices from it. This all sounds fairly straight forward and the code to call the devices page using the android-async-http library looks like this.

AsyncHttpClient client = new AsyncHttpClient();
client.setBasicAuth("API_KEY", "",
				new AuthScope("pushbullet.com", 443, null));
client.get("https://www.pushbullet.com/api/devices", new AsyncHttpResponseHandler())

This should all have worked but it doesn’t. Looking at the logs, I always saw the same error

04-23 08:52:12.845: W/DefaultRequestDirector(21976): Authentication error: Unable to respond to any of these challenges: {}

Googling around, it seemed that the error was that the server did not tell the client that it used basic HTTP auth but simply said we were “Unauthorized” to view this webpage. A proper configuration of the server would have resulted in our client receiving a list of challenges to reply with and would have sent the basic auth to the server. The HTTP client library does not send the basic auth credentials in the first request to the server but only when the server says that it needs these credentials. The alternative now is to send the basic auth to the server with our initial request.

To do that however, we must first encode our username and password.

String encoded = new String(Base64.encode("API_KEY:".getBytes(), Base64.NO_WRAP));

And then pass this encoded string in the “Authorization” header of our request.

client.addHeader("Authorization", "Basic " + encoded);

That’s it, because the Basic auth credentials are not sent to the server with the initial request the server replies back with proper JSON data.

I spent a good 6 hours trying to figure this out, I hope others don’t have too.

Comments Off (458 views)
February 27th, 2013 | Tags:

At work I have been using robotframework to write acceptance tests. And while I cannot say that I absolutely love it, I can see how the framework is useful despite its somewhat minor shortcomings. I have used FitNesse in the past and it’s a little difficult to pick a favourite at this point, they both seem to have their pros and cons although I must say that FitNesse with its built in HTML editor is definitely has an edge on RF.

Anyway, I was writing test cases and I came to the point where I needed an if statement that AND’d a few variables and then executed logic. The statement itself was very simple

Keyword Argument 1 Argument 2
Run Keyword If '${field1}' == 'FIELD1' && '${field2}' == 'FIELD2' My Keyword

I couldn’t find any way to do this in the robot framework and the documentation didn’t help so I went hunting. An informative post from the RF mailing list told me that RF supports all logical operators that are in the python language. I don’t know python so I had to go looking.

Python supports logical operators just like any other language and these can be directly used in RF. So my AND/OR conditions in RF are written as

Keyword Argument 1 Argument 2
Run Keyword If '${field1}' == 'FIELD1' and '${field2}' == 'FIELD2' My Keyword
Run Keyword If '${field1}' == 'FIELD1' or '${field2}' == 'FIELD2' My Keyword

As simple as that.

Comments Off (284 views)
February 27th, 2013 | Tags:

I can no longer deal with the amount of spam posted in comments. I have, therefore, disabled all comment posting on my blog.

Spammers, you win.

Comments Off (225 views)
February 28th, 2012 | Tags: , , ,

Ahh, the joys of JIRA. It’s hard to argue that JIRA is not the best bug management system out there when you see that they support a host of external access protocols. SOAP is (understandably) the preferred method of access and there is a nice example of its use on the Atlassian wiki.

I wanted to see if I could access JIRA with Groovy also and perhaps present the data in a pretty looking desktop app built using griffon. I couldn’t find any obvious examples but then I stumbled across the JIRA SOAP lib.

The JIRA access itself is pretty straight forward, you just define a URL to JIRA and the JiraSoapServiceServiceLocator of the SOAP lib does the rest, pretty nifty.

def server = 'http://jira.iontrading.com'
def url = "${server}/rpc/soap/jirasoapservice-v2"

def serviceLocator = new JiraSoapServiceServiceLocator()
serviceLocator.setJirasoapserviceV2EndpointAddress(url)
serviceLocator.setMaintainSession(true)

We must first generate a login token which is sent with every SOAP request to the server. This is your ‘cookie’.

def service = serviceLocator.getJirasoapserviceV2()
model.loginToken = service.login(model.username, model.password)
println "Login token - " + model.loginToken

Ignore the model prefix, I save the username and password in the griffon model.

Once you’re logged in you can print server info.

def info = service.getServerInfo(model.loginToken)
println "JIRA version: ${info.getVersion()}"

And also execute JQL queries.

def issues = service.getIssuesFromJqlSearch(model.loginToken, model.query,20)

“issues” above is a RemoteIssue array returned. You can all attributes of the issues from this query.

In the sample application here I group the issues by a custom field and display them in a JXTable. This custom field is out Greenhopper story point field.

The fun part of writing all this code is that at the end you know what you’re going to get is not same half baked solution but a fully functional GUI.

The useful part of writing all this is that the application is easily extensible, you just need to add a new tab and you can group your issues according to any criteria you want. Oh, how I enjoy griffon.

0 comments (1,545 views)
February 16th, 2012 | Tags: ,

Ever since I started using github for hosting I have started to dislike SVN. Don’t get me wrong, its still very useful and easy to understand but as a developer I don’t want something that is easy to understand (infact I won’t be able to use such a tool) but I want something that works well. Today I found a little gem of a tip hidden on SO related to SVN.

One of our new builds was setup yesterday and it just refused to run giving an error saying that the shell script it was trying to execute did not correct permissions. Hmm, odd, this works on windows. (Ofcourse it does, you don’t execute .sh scripts on windows! Duh!) It was obvious that the scripts permissions needed to be changed with `chmod +x script.sh`.

I did that and ran a `svn diff`. No changes. Hmm, that’s odd, I just changed a file, shouldn’t it see this as a change and show me a diff… Apparently not. Subversion does not store file permissions so then how can I make it checkout the correct permissions for scripts that need them?

I thought about this for a few minutes and was about to give up and just run chmod via ant builder in a groovy script when I thought to look this up on SO. The same question has been asked before. And it has just the answer I was looking for, though buried under a few other no-so-useful answers.

For the lazy ones, you need to set a property “svn:executable” on the file where you want to set files to be executable. Subversion then maintains this bit and passes this onto the operating system. Not as flexible as just maintaining the original permissions but it works. Here is the explanation of the property from the svnbook:

svn:executable

The svn:executable property is used to control a versioned file’s filesystem-level execute permission bit in a semi-automated way. This property has no defined values—its mere presence indicates a desire that the execute permission bit be kept enabled by Subversion. Removing this property will restore full control of the execute bit back to the operating system.

On many operating systems, the ability to execute a file as a command is governed by the presence of an execute permission bit. This bit usually defaults to being disabled, and must be explicitly enabled by the user for each file that needs it. In a working copy, new files are being created all the time as new versions of existing files are received during an update. This means that you might enable the execute bit on a file, then update your working copy, and if that file was changed as part of the update, its execute bit might get disabled. So, Subversion provides the svn:executable property as a way to keep the execute bit enabled.

This property has no effect on filesystems that have no concept of an executable permission bit, such as FAT32 and NTFS. [28] Also, although it has no defined values, Subversion will force its value to * when setting this property. Finally, this property is valid only on files, not on directories.

0 comments (1,418 views)
February 14th, 2012 | Tags: , , , ,

Parsing HTML documents is never easy. Some languages have better support for such tasks than others. I thought Groovy wasn’t one of them but I was wrong. I had to parse a HTML document that wasn’t always well-formed and that made the task harder. Dennis’ post was very useful when I was getting started. The post introduced me to TagSoup parser which is a very useful Java library for parsing HTML.

I eventually did not use TagSoup but instead ended up using NekoHTML. I had to parse a HTML that wasn’t always formed the same way. For example,

        <head>
            <title>Hiya!</title>
        </head>
        <body>
            <table>
                <tr>
                    <th colspan='3'>Settings</th>
                    <td>First cell r1</td>
                    <td>Second cell r1</td>
                </tr>
            </table>
            <table>
                <tr>
                    <th colspan='3'>Other Settings</th>
                    <td>First cell r2</td>
                    <td>Second cell r2</td>
                </tr>
            </table>
        </body>

This HTML isn’t well formed and if I had to parse it I would be lost if someone decided to insert a TBODY tag in the table. This is where NekoHTML comes in. It converts this HTML into well-formed XML that can then be read by XmlSlurper.

First we define the parser.

def parser = new org.cyberneko.html.parsers.SAXParser()
parser.setFeature('http://xml.org/sax/features/namespaces', false)

We must set the parser to ignore namespace because we don’t really care about it. The parser has a host of other options that can be set including the ability to remove certain elements. I haven’t tested this (because I couldn’t get it to work with Groovy) but I can imagine that this can be very useful sometimes when you want to get rid of text formatting in HTML.

Next, define our slurper giving it our newly created parser. Ask the slurper to parse the text and we get a page.

def slurper = new XmlSlurper(parser)
def page = slurper.parseText(html)

Because our slurper is “groovy” we can now access the body of the HTML document directly without the need to execute GPath expressions although that is still possible to do.

As an example, I wanted to find the first table that had a particular heading. In the HTML above this is the table with heading “Settings”. To do this you just do. Disclaimer: I had help from SO where I asked how to do this.

def settingsTableNode = page.BODY.TABLE.find { table ->
  table.TBODY.TR.TH.text() == 'Settings'
}

I can now access all other rows of the table because I have the table node with me. This makes scraping extremely easy to do. I can read parts of the table that I want or perform further “find” on the table node to get other sub-entities.

Groovy doesn’t only make XML parsing easy but also HTML parsing. :)

0 comments (2,410 views)
February 12th, 2012 | Tags: , ,

I’ve started expermenting with griffon again and I learnt a cool new trick today. Pre-0.9.2 all controller actions were called within the UI thread. This meant that if you needed to do anything long-running you’d need to move it to a separate thread or your application would become unresponsive (atleast in the eyes of the user).

Post-0.9.2 this is no longer necessary because all actions in a controller are called outside the UI (or EDT) thread. This is not a griffon specific feature but is present in groovy’s SwingBuilder. It’s now trivial to execute code within the edt. As an example, I want to build a file chooser within the controller when an ‘Open File’ action is invoked.

First, define a filechooser in your controller and then initialize within the edt thread.

def fileChooserWindow;
edt {
	fileChooserWindow = builder.fileChooser(currentDirectory: baseDir, dialogTitle: 'Choose an Html file',
					fileSelectionMode: JFileChooser.FILES_ONLY)
	openResult = fileChooserWindow.showOpenDialog(view.mainFrame)
}

The swingbuilder then ensures that your code executes within the edt and because the last call is blocking in nature till the user replies the rest of your controller does not execute. This is extremely convenient because you can now execute UI actions from the controller by dynamically creating UI components as and when you need them and even disposing of unused components.

Note: Andres Almiray suggested that I prefix the fileChooser initiailization with a builder because “… nodes are not added to controllers. You must define a builder property on the controller”. I don’t quite know what that means but because it’s Andres, I went ahead and did it.

In case you’re wondering what baseDir is, its initialized like this in my controller.

def baseDir = Metadata.getCurrent().getGriffonStartDirSafe() as File

The Metadata class is a very useful class that you can use to access information about your application.

1 comment (16,914 views)
October 20th, 2011 | Tags:

It’s frustrating to find all your settings gone when you upgrade eclipse versions and if you’re pedantic about certain settings (like I am) it can take you almost an entire day to upgrade versions (with everything working just the way you like it). With Indigo, fortunately, none of the manual settings were necessary. There was a very nice import wizard that allowed me to import my old Helios installation. The wizard is in File->Import->Install->From existing installation.

I was really hoping everything would go as planned but it didn’t. (It’s okay, I had very little expectation it would) Maven refused to build any projects. I checked the maven version and it was the embedded one. I figured since this was a little older than the latest maven3 release, it could be causing problems so I changed the installation to use a manually installed version of maven.

No dice. After a few minutes of searching, I found the problem (or so I thought). The maven builder that eclipse was using was missing.

That’s odd. Maven integration is built into Indigo now so there is no reason why it shouldn’t find the builder. Not good. I tried a few things but then I found this very useful thread on stackoverflow. It turns out that the .project eclipse files weren’t updated correctly. I right clicked on the broken projects and saw an option to “Convert into maven project” in the Configure menu.

On clicking this option, eclipse “transformed” my project into a maven project. I checked the .project and noticed that it had added another builder in there. All good but the project still doesn’t build. Grrrr… Check the builders again and this is what I see

Why didn’t it remove the useless builder? If I uncheck the missing builder my build still doesn’t run! Argh.

I see a dependency which doesn’t look like it should be in my build path, this is added because of the old builder (which I hate by now).

Once I remove this dependency from the build path it works! I’d suggest that you not upgrade eclipse on a weekday like I did (on a Wednesday too!) because this is one of the more frustrating downsides of eclipse. Hopefully, the next upgrade will be easy(hah!).

0 comments (2,599 views)
July 20th, 2011 | Tags: ,

I am unwell and stuck at home so I decided to dive into my Android app (a new one this time!). I wanted to perform some tasks that could be long running (doubtfully but why freeze the UI thread ever). I want to show a ProgressDialog here but it doesn’t work with the static factory method, ProgressDialog.show(…). I keep getting the same exception again and again.

07-20 22:57:16.445: ERROR/AndroidRuntime(25843): FATAL EXCEPTION: main
07-20 22:57:16.445: ERROR/AndroidRuntime(25843): java.lang.NullPointerException
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.app.ProgressDialog.onProgressChanged(ProgressDialog.java:318)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.app.ProgressDialog.setMax(ProgressDialog.java:233)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at com.codercorp.android.playlist.ExporterTask.onPreExecute(ExporterTask.java:68)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.os.AsyncTask.execute(AsyncTask.java:391)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at com.codercorp.android.playlist.PlaylistExporterMain.onClick(PlaylistExporterMain.java:81)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.view.View.performClick(View.java:2485)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.view.View$PerformClick.run(View.java:9080)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.os.Handler.handleCallback(Handler.java:587)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.os.Looper.loop(Looper.java:130)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at android.app.ActivityThread.main(ActivityThread.java:3683)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at java.lang.reflect.Method.invokeNative(Native Method)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at java.lang.reflect.Method.invoke(Method.java:507)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-20 22:57:16.445: ERROR/AndroidRuntime(25843):     at dalvik.system.NativeStart.main(Native Method)
07-20 23:02:38.425: ERROR/jdwp(25924): Failed sending reply to debugger: Broken pipe

After googling for a good amount of time I came across this bug report in the Android project http://code.google.com/p/android/issues/detail?id=3114. The report’s been up for over two years now but Google hasn’t bothered to fix it (shame!). As is mentioned in the report, the problem is with the update handler variable not being set before the dialog box is shown. The solution is simple, create your own ProgressDialog without using the static factory method.

ProgressDialog progressDialog = new ProgressDialog(PlaylistExporterMain.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(false);
progressDialog.setMax(getListAdapter().getCount());
progressDialog.show();

If you have run across this bug, please go to the bug report and leave a comment, maybe it’ll force Google’s hand into fixing the bug (which requires an addition to the ProgressDialog static factory methods).

3 comments (5,371 views)
May 29th, 2011 | Tags: , , ,

I woke up today morning all charged up to work on my app again (barely slept yesterday). The fist thing I wanted to do was to add a progress dialog to my applications list activity. The activity isn’t time consuming (not much anyway) but you don’t want the UI to be unresponsive, gives a bad impression to the user.

So while the UI thread is busy on my onCreate doing stuff for me I want to show a loading dialog box. Easy right? Not really. Unless you’re an android expert (and I am not) there are a lot of pitfalls. There are things you need to work around. For example, displaying the dialog box in the UI thread, performing the activity in it and then hiding the box doesn’t work and isn’t a good idea anyway.

You must update the main UI from a separate thread. To do this I had to spawn another thread in my main onCreate method. While this does not seem ideal to me at all (I hate working with threads directly), I’m going to do this for the purposes of this example anyways.

Note: I couldn’t get the default progress dialogs to work, so we will create our own in this example. Once I get the default dislogs to work, I will put up another article.
Note2: My default activity extends ListActivity.

First, some code to create the ProgressDialog

final ProgressDialog dialog = new ProgressDialog(this);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.setMax(100);
dialog.show();

Remeber to create the dialog before you do anything else with the UI like register for context menu create etc. If you don’t then you will get an exception.

Once we’re done with the dialog box, we go ahead and spawn our worker thread.

		Thread myThread = new Thread(new Runnable() {
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				dialog.setProgress(100);
				dialog.dismiss();
			}
		});
		myThread.start();

See the line setting the progress to 100. This is the max progress we hve to set. If you don’t set the progress to a value equal to the max progress then the dialog box won’t go away even if you call dismiss() on it. I spent a good half hour wondering why the bar wouldn’t go away because of this.

And that’s it, your dialog box is ready. The full activity code looks like this:

public class HelloAndroid extends ListActivity {

	private List<PackageInfo> packages = new ArrayList<PackageInfo>();

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final ProgressDialog dialog = new ProgressDialog(this);
		dialog.setCancelable(true);
		dialog.setMessage("Loading...");
		dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		dialog.setProgress(0);
		dialog.setMax(100);
		dialog.show();

		registerForContextMenu(getListView());
		
		Thread myThread = new Thread(new Runnable() {
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				dialog.setProgress(100);
				dialog.dismiss();
			}
		});
		myThread.start();
		setListAdapter(new MyAdapter(this, packages));
	}
0 comments (18,664 views)
May 29th, 2011 | Tags: , , , ,

After spending two weekends reading up on the SDK and in general playing with my new Google Nexus S, I finally decided to get my feet wet. Downloading the SDK wasn’t really a breeze because the data size is large and with my crappy internet it took forever. When I finally got to writing code, I was plesantly surpised by the ADT plugin, it works flawlessly.

Anyway, I decided I wanted to list all the packages installed on the emulator in a two line list view. You’d think this would be a breeze, it was anything but.

I struggled for a while with NullPointers all over the place before I came across this example in the SDK. Despite stackoverflow, I couldn’t find what I needed on the internet and the example was what eventually helped me.

Anyway, to the example cave! Because we want our default view to be a list view our main class must extend a ListActivity instead of an Activity.

public class HelloAndroid extends ListActivity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

The code to retrieve all installed applications on the system is pretty straightforward.

		final PackageManager pm = getPackageManager();
		List<ApplicationInfo> packages = pm
				.getInstalledApplications(PackageManager.GET_META_DATA);

		List<ApplicationInfo> list = new ArrayList<ApplicationInfo>();
		for (ApplicationInfo packageInfo : packages) {
			list.add(packageInfo);
		}
		setListAdapter(new MyAdapter(this, list));

Next, we use the default android layout and create an adapter that extends from the BaseAdapter class. We need a custom adapter because by default the ArrayAdapter displays the toString() of objects present in the array. And we can’t use a SimpleAdapter because we don’t have a cursor. Extending the BaseAdapter allows us to customize the view to our needs and display what we want in whichever element of the view we want.

class MyAdapter extends BaseAdapter {
	private LayoutInflater mInflater;

	private List<ApplicationInfo> list;

	public MyAdapter(Context context, List<ApplicationInfo> list) {
		mInflater = LayoutInflater.from(context);
		this.list = list;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.list_item, parent, false);
		}
		TextView title = (TextView) convertView.findViewById(R.id.item_title);
		TextView sub = (TextView) convertView.findViewById(R.id.item_subtitle);

		ApplicationInfo info = list.get(position);
		title.setText(String.valueOf(position));
		sub.setText(info.processName);
		return convertView;
	}

	public int getCount() {
		return list.size();
	}

	public Object getItem(int arg0) {
		return list.get(arg0);
	}

	public long getItemId(int arg0) {
		return arg0;
	}
}

Setting this adapter as the data provider for our list view is simple. The tricky part is making sure you get the id’s of the children view right (this one took me a while to figure out). So our final HelloAndroid class looks something like this.

public class HelloAndroid extends ListActivity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final PackageManager pm = getPackageManager();
		// get a list of installed apps.
		List<ApplicationInfo> packages = pm
				.getInstalledApplications(PackageManager.GET_META_DATA);

		List<ApplicationInfo> list = new ArrayList<ApplicationInfo>();
		for (ApplicationInfo packageInfo : packages) {
			Log.d("TAG", "Installed package :" + packageInfo.processName);
			Log.d("TAG", "Launch Activity :" + packageInfo.className);
			list.add(packageInfo);
		}
		setListAdapter(new MyAdapter(this, list));
	}
}

This will display all the installed packages on your device in a neat list view. This code isn’t efficient because we query the packages in the UI threads. The ideal solution would be fire this off as an Intent and then query packages in the intent, displaying them and notifying the view that the data has changed. The use of the default ListActivity however does allow for auto-scrolling loading. This means that only what is visible on the screen is shown at the beginning and as and when you scroll down, more and more elements are rendered. This is very efficient from a UI perspective escpecially when the UI is running on a device which has limited resources (1GB RAM can run out pretty quickly).

I’ll be writing more on how we can fire off an Intent and then loa

2 comments (8,885 views)
May 28th, 2011 | Tags: , , ,

I blogged about reading a jar’s manifest file recently but what use is reading a manifest unless it contains something useful. In a development environment where we are constantly pushing SNAPSHOT’s to others, it helps to know what version of your code base others are using in order to debug problems.

Two properties here are especially useful, the version of your jar and the time it was built. To include these through maven, you must use the maven jar plugin to add the properties to your jar’s manifest at build time.

The configuration is simple, in the build section of your pom.xml add the following plugin:

			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
				&lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
				&lt;version&gt;2.1&lt;/version&gt;
				&lt;configuration&gt;
					&lt;archive&gt;
						&lt;addMavenDescriptor /&gt;
						&lt;manifest&gt;
							&lt;addDefaultImplementationEntries /&gt;
							&lt;addDefaultSpecificationEntries /&gt;
						&lt;/manifest&gt;
						&lt;manifestEntries&gt;
							&lt;ComponentVersion&gt;${project.version}&lt;/ComponentVersion&gt;
							&lt;BuildTime&gt;${maven.build.timestamp}&lt;/BuildTime&gt;
						&lt;/manifestEntries&gt;
					&lt;/archive&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;

And that’s it. You’re done.

I believe it would also be useful to add the revision number of the build but I haven’t quite figured out how to do that yet, so that’s for another time.

0 comments (2,875 views)
May 28th, 2011 | Tags: ,

I just started developing an app to try my hand at Android SDK. The first problem I ran across was that the HellowWorld android app part of the exercise on the SDK site wouldn’t deploy.

I kept getting, “Failed to install HelloAndroid.apk on device ‘emulator-5554! “. And I kept restarting the emulator. This was a big mistake. After a lot of googling, it turns out that the emulator takes a while to load and when it loads it displays the phone’s UI and not the words “android”. If you restart your emulator then it’s going to go through the whole booteup process again.

It’s a bit weird that there is no clear indication of when the emulator is fully up and running but I generally wait till I see the screen appear till I start to deploy any applications.
Running emulator

Also, you might want to increase the RAM on your AVD image to 1024. It seems that it boots up faster when it has more RAM but I have no proof to share so I can only say try it, might just work for you too.

0 comments (2,403 views)
May 26th, 2011 | Tags:

At work, we have multiple libraries that provide us with small small functionalities. This design keeps things simple and makes code sharing easy. But it also has it’s own set of problems. In very large projects where there are multiple branches and complicated dependencies, it’s impossible to ask customers to provide you with jar versions. The easiest way to is to have this version saved somewhere and then to print it in logs automatically.

Where do you save this version though? A file is a good choice but it’s not the right choice when things like a MANIFEST that’s supposed to hold meta information. A manifest is what we chose as well (especially because editing files as part of the release process, using the maven release plugin, isn’t supposed to work).

The primary task for us was that we had many such modules which wanted to print their version numbers. We would have to identify the exact manifest file to read and then print it’s version. As simple as this may sound, the JDK provides no help with this at all. The code, once you see it, will looked like someone hacked up a cat and put it within curly braces.

Before I list any code, I’d like to give a shout out to the folks at stackoverflow.com for the community and their work. I found what I was looking for there in this thread. Without stackoverflow’s community, I wouldn’t be able to find half the things that I am looking for because let’s face it, Google isn’t really Google anymore.

The simplest piece of code that I could write to extract a manifest file from a specified class file:

        Class clazz = this.getClass();
        String className = clazz.getSimpleName() + ".class";
        String classPath = clazz.getResource(className).toString();
        if (!classPath.startsWith("jar")) {
            // Class not from JAR
            return null;
        }
        String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
        Manifest manifest = null;
        try {
            manifest = new Manifest(new URL(manifestPath).openStream());
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }

The main aim is still not achieved though, we want any and all classes to be able to do this. So any calling class must be able to retrieve it’s own manifest file easily. This means that the above code needs to be changed slightly to that it can accept a class externally rather than using “this”. And also that the caller is passed implicitly.

To obtain the caller:

        Class<?> caller = null;
        try {
            caller = Class.forName(new Throwable().fillInStackTrace().getStackTrace()[1].getClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace(System.err);
        }

And pass this “caller” to the code above. You have your manifest to read from now.

0 comments (3,789 views)
November 19th, 2010 | Tags: ,

I’ve been playing around with Griffon lately and I must say I am very impressed. The more I use it, the more I go, “Why didn’t someone bring mvc development to Swing before?” Perhaps they did. I wasn’t rally paying attention to Swing for the last 5 years or so because I there was just way too much noise in swing applications. I could go on with this rant but …

Anyway, Griffon simplifies a lot of things. One of them is setting the look and feel of your application. No one is very impresses with the default java swing app LAF so I decide to see where Substance is these days and installed the substance plugin. That’s another nice feature of Griffon, plugins, no more dealing with jar’s and configuration files to get your hands dirty. That automatically adds the substance jar to my classpath.

Next on the list of things was the LookAndFeel plugin. Easy enough. Now to make sure that when my app starts up the substance LAF is used by default. For that open the Config.groovy file in you griffon-app/conf folder and add the following lines to it:

lookandfeel {
	lookAndFeel = 'Substance'
	theme = 'Business'
}

And that’s it. None of that messy UIManager stuff and exception catching!

0 comments (3,357 views)