January 2009

Jan 26, 2009

In this post I will explain how to invoke Web Services from within Eclipse. Just to be clear, I'm not discussing a full blown networking application. For that you would probably use the Eclipse Communications Framework (ECF). It is a simple case: one service that needs to be invoked. On the face of it, it should be very simple. This is Java, which was built for handling XMLs and web oriented tasks. There's a very popular Web Services stack called Apache Axis2. It is fairly simple to use and there are plenty of tutorials for using it. So why another tutorial?

The Challenge of Connecting From Eclipse

Not so fast. There's a "minor" catch here. You see, from my experience with my Eclipse plug-in, this will fail in many cases. Why? There are a number of reasons, most of them are around firewalls and proxies. Most users in the corporate world are sitting behind both a firewall and a proxy. For the invocation to work, the firewall should enable the communication from the Java process and the proxy needs to be properly defined in Eclipse.

Many firewalls today block the Java processes. Probably because it is just so easy to write a malicious Java applet that will sit on the client machine and send sensitive information to a remote attacker. In some distributions, the Eclipse process identifies as Eclipse and in other cases as plain Java. The behavior varies and it is hard to predict how the corporate firewall will react. As for proxy configuration: in Eclipse 3.3 this had to be defined manually in the Eclipse preferences. From Eclipse 3.4 there's a new default "system proxy configuration (if available)" settings. This might work in Windows. I'm not sure about other operating systems.

The bottom line is this: you just cannot rely on communicating with the outside world from within Eclipse. There's one exception to this, which makes this article worth writing: The SWT Browser Control.

The Browser control, like other SWT widgets, is a thin wrapper on top of native operating system UI elements. When you try to access the web from the browser control, this is the same as using the operating system default web browser. The identification of the process is the same ID as the browser so the firewall will allow the outgoing communications. The proxy settings are the settings the user configured in the browser. If the default web browser works, the browser component will work. This greatly improves the odds of getting through.

Sending a Request

Sending a request with the Browser widget is the same as invoking web services from a regular web browser. If the request can be a simple GET request, just enter a URL and send the request. If the request must be a POST request (e.g. due to the length of the parameters), you will need to have an HTML page with a form for submitting the request. We will deal with the simple GET case, so the code will look a bit like this:

Of course, we need the parent element. If this is part of a UI operation, this should be no problem. If it is not, you can get the default shell, but this is not enough. You also need to make sure you will be running in the UI thread by using something that will look a bit like this:

Notice that this is a synchronous operation since we are looking for a response, and this is what we will do next.

Receiving a Response

The response will be available when the browser is finished processing. Since this is a synchronous operation, we need to wait until the process is complete. Naturally, we should also expect a timeout. The best way of finding out when the browser is ready is to use a process listener. The listener class will look a bit like this:

We still need to access the resulting text, which exists inside our anonymous class. To do that, we will convert our anonymous class to an inner class. The end result will look like this: (click here to get a complete Java file)

Note that the above code does not handle timeout or reporting progress to the user. I leave this to the reader and it is possible that I will cover this at a later post (let me know if you're interested). There's also a limitation to the above approach: it will not work while the platform is loading. You will have to wait until it is up and running.

Processing the Result

There is one big drawback to this approach: the result is what you get from the browser. Assuming your server is sending back an XML, this may be a problem since each browser has its' own way of presenting XMLs. Internet Explorer will add fancy expand/collapse controls while Firefox and Safari take a cleaner approach. When using browser.getText() you get the HTML from the browser (same as using "view source" in your browser) which may include CSS, JavaScipt and other tidbits. Since you cannot tell which browser will serve you, you cannot rely on the structure of the result.

In my case, I was controlling the server, too, so my solution was simple: send the response as one big encoded string with a unique prefix and suffix. While processing the response, the client would look for the prefix and suffix, and ignore everything in the middle. This solution works well on IE, Firefox and Safari on Windows, Mac OS X and Linux Ubuntu. This is fairly simple task. I used a piping of streams to serialize and de-serialize objects as one encoded string. The streams I used: ObjectOutputStream, GZIPOutputStream and Base64.OutputStream (from iharder.net/base64)

Summing Up

In this article I presented a practical approach for invoking a web service from inside Eclipse. Unlike usual communications done from within Eclipse, this method is almost guaranteed to succeed if the machine is connected to the internet. Got a simpler way? Let me know.

Jan 19, 2009

Last week, Apple announced that more than 500 million apps were downloaded in the App Store. There are over 15,000 available apps to choose from.

Most articles about this chose to deal with the quality of these applications (like here and here). I want to remind you of something else. When Apple began shipping its' iPhone SDK there was a lot of racket. We are at enlightened times of open source and transparency and along comes Apple with its' closed platform and malicious NDAs. What were they thinking?

The app store is the only way to get apps on to the iPhone (unless you hack your device), but publishing your apps there is not a walk in the park. The process is complex and it undergoes rigorous screening. If you do get there, they share your profits, which are not that big to begin with since the apps are really cheap.

Seems like they had all the reasons to fail. Yet, they didn't.

You know what? It's obvious to me why. From the same reason the iPod is such a huge success to begin with. Sexy UI with a complete, end-to-end amazingly simple user experience.

But that's not the reason I wrote this post. I wrote this post because there's a lesson here. Even in these enlightened times closed, proprietary platforms will succeed. Because the end user doesn't care. The developer cares. But she cares more about getting paid.

Some general background is in order for non-Mac users (or Mac users which didn't see the light). Quicksilver is a general launch utility for Mac. It was designed by Nicholas Jitkoff from Blacktree, which is now a Google employee. I recommend this 25 minute tech-talk about Quicksilver. It's more than a year old, but still innovative and interesting.

I'll pick two important points from the talk. First, Quicksilver is built on a philosophy: Act Without Doing. Basically, this means you are performing an action as part of your flow, without interruption and with minimal effort. An example would be: I'm working on a document and suddenly remember a task I need to do. If I can use a single keystroke to bring a small box, write my task and dismiss it - that is minimal effort with no interruption to the flow. Unlike a case where I would have to switch to my task management application.

The second issue to understand is how actions are performed in Quicksilver:

Search for the object by typing its' name (can be partial name).

Select the object from the list of results.

Browse to associated objects until you find the object you specifically target.

Perform an action on that object: select from a relevant actions which are appropriate to the specific object. You might need to provide some extra parameters to do that.

For example: I want to send an email. I search for a contact name by typing his name. I find a number of matching contacts and select the appropriate one. From there, I browse all the contacts given addresses and select the one I want to address. I choose the action: send email. For a contact, other actions may be relevant like send to my mobile phone. Finally, I provide the email text and the email is sent.

My question is: how do we implement this in the IDE? It seems like a very complex environment that could use simplifying.

The object being searched can be a component (type, interface, method, field, spring bean definition, etc.). Browsing associated objects would mean tracing component associations like class which extends another class or implements an interface. Maybe a method which modifies a field or invokes another method.

Once you located your target component, what actions would you want to perform? Here are some thoughts:

Open the source file. This is trivial.

Show associated components. Well, that's what happened when we were searching for the component.

Depending on the component type: show documentation, set up a breakpoint, check it into the source control, open a defect related to the element, add it to a workspace. You can probably think of other actions.

nWire, the Eclipse plugin I've been working on for some time, takes this about 80% of the way. It lets you search and browse. It currently performs only the single action of opening the source file, which is the most important. However, this is just a first release, so expect this to expand.

I took a bit of a different approach, of using an integral view (see some screenshots) rather than opening a dialog box. Mostly because that this seems more useful to the flow of coding. It takes a bit more space, but it gives you a lot more. Nevertheless, I'm considering a future option to show it in a way which is more Quicksilverish.

Another common feature is the ability to extend the catalog of components. Quicksilver has a plugin mechanism which allows adding new type of components and associations. For example, adding bookmarks from del.icio.us to the catalog. nWire, is also built for extending and adding components from different programming languages and frameworks. The initial version is Java only, but this is just the beginning.

Jan 11, 2009

Here's another FAIL. A new web site monitoring service was mentioned in Lifehacker today. This, in turn, pushed a surge of traffic to the site, which, in turn, collapsed. Having your site collapse from traffic is like a badge of honor for a startup. However, when your site is called "are my sites up" there's something ironic about it, don't you think?

Jan 04, 2009

During the development of my Eclipse plug-in (nWire) I had to test and fine-tune the behavior of the plug-ins upon startup. It's an annoying situation: you only have one shot for testing your code. If you want to retest, you have to stop and start over. This is especially annoying when loading Eclipse takes more than 10 seconds, which is usually the case.

I found a simple solution which allows me to have a fully functional Eclipse instance in about 2-3 seconds. It is very simple to implement and can save a lot of time (and annoyance).

The solution is simple: disable all the plugins which are not necessary for your Eclipse instance to execute properly. This task is very simple if you know how... so here goes:

Create a new Launch Configuration for your plug-ins or start from an existing configuration and duplicate it. Naturally, it should be of type Eclipse Application. The fastest way to create such a configuration is to open the plugin.xml and click on "Launch as Eclipse Application".

Go to the third tab titles "Plug-ins".

In the top drop down "Launch With" select "plug-ins selected below only".

Click on "Deselect All".

Select your plug-ins from the list. They will appear in the top section, under "Workspace".

Click "Add Required Plug-ins".

Done. Click apply and you are ready to launch your configuration.

A word of caution: this only works if you correctly define the required plug-ins for each of your newly developed plugins. If not, you will immediately notice the problem. This makes it a great way to test the correctness of your dependencies.