Sunday, April 11, 2010

Thoughts on Flash (the Eclipse way)

Funny coincidence but definitely not related to Apple vs. Adobe shootout, my team was required to integrate an existing Adobe Flash application into Zend Studio 7.2.0 (an Eclipse PDT based product). Let's share this experience of integrating Eclipse and Flash:

Reusing Flash or Writing plain SWT?

It started as a simple and common requirement to provide a presentation layer for a given data source loaded into the product. Happy and enthusiastic we started designing a user friendly Eclipse perspective that provides nice diagrams and trees that present the data. Before we started to actually implement it, we were told that it would be great if we can reuse an existing Flash application that our colleges at Zend have already developed. "Adobe do this so why can't we do this?", relating to Flash Builder that is based on Eclipse and Flash. Anyway, it can save months of development and integration effort in the future.

The Good

Using a Flash application into Eclipse integrated web browser is pretty easy task. Users choose a source file in a dedicated import wizard, a new perspective is presented that includes an Eclipse view presenting the Flash application. We used a simple browser view for this end:

public class FlashView extends ViewPart {
private Browser browser;
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
try {
int mozilla = SWT.MOZILLA;
browser = new Browser(parent, mozilla);
} catch (SWTError e) {
// ...
private String getText(String file) {
return "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
width='100%' height='100%'>
<param name='flashVars' value='...'>
<param name='src' value='myFlash.swf'>
<param name="wmode" value="opaque">
<embed pluginspage=''
width='100%' height='100%'

And a Jetty server for serving the Flash application is launched:

public class JettyServerManager {

public static void startJettyServer(final int port) throws Exception {
final String rootPath = getJettyRootPath();
Runnable runnable = new Runnable() {
public void run() {
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();

try {
} catch (Exception e) {
// ...
serverThread = new Thread(runnable);

public static void stopJettyServer() throws Exception {
if (server != null) {
// ...

The Bad

One more trick that we wanted to add in our client product is a small layer of communication between the two applications, so basically once a user clicks on a data relating to a specific workspace resource the relevant resource is opened in the editor (something like "link with editor" button).

Our first attempt used a dedicated socket to transfer these calls, but after reading the cross-domain policy we understood that another port is required. So three (!!!) different ports are opened for serving this application - the Jetty one, our communication channel and a cross-domain policy port (since the default one is 843 and Linux based OS can't open it we should have open another non-default one). We could live with it if it worked out, but after lots of testing it came out that Windows and Linux machines don't behave the same. On Windows the security port got the request and handles it right, then the actual communication port works as expected. On Linux the same workflow is expected but we got garbage content in our communication although the policy file was excepted and verified by the Flash engine.

Our next attempt used the same Jetty channel to broadcast the changes from the Flash application, once the Flash application wants to alert our product it sends a request to the Jetty (on the same port) and notify our product. This actually worked very nicely.

The Ugly

Well, let's say that Flash and SWT don't share the same look and feel and are naturally different. Usability in this case is a little awkward but tolerable.
To make sure our customers are not required to manually install a browser and then install a Flash player plugin on top of this browser we wanted to have our own XULRunner instance and flash player plugin installed. Although it seems that Adobe's Flash player license is pretty open we couldn't redistribute it in an easy way into our integrated browser as Adobe require to install it under a specific place using their installers.
One last usability shame is the case where an instance of a Flash view is opened and then Eclipse product is closed. Although the Jetty service is down as well (as expected) it should be launched again to serve the view again upon start.

The End Result

A simple import wizard that requires the stored snapshot is displayed:

Many thanks to Qiangsheng Wang and Jacek Pospychala!