Wednesday, February 28, 2007

Creating a multiplatform installer (with IzPack)

Hello once again.
As promised, today I'll talk about how to create your multiplatform installer for your Eclipse Rich Client Application without having to add all the folders PDE (Plugin Development Environment) created.

First of all, understand that what I'll explain for IzPack can be used for any other installer you like. Just search for a feature similar to the one I quote in your installer and you should have no problem.
Now that this is explained, let's get started:
First of all, part of your jobs is already done thanks to the eRCP imposed architecture. I'm talking about having your project split in several parts that are almost completly independent. This is very useful since it'll allow your user to choose the plugins he wishes to install.
This reminds me of something: feature != plugins.
Your update site or your product uses a set of plugins and call it a feature if you followed most of the tutorials. This doesn't means your installer must care about your feature definitions.
The feature definition will allow your update system to know which updates it should look for and which features are considered "new features". This means that if your application is running without any feature and you ask for an update, it'll show you the core feature (which you obviously already have since you're running your application) as a "new feature" to be installed. That can be explained by the fact that sites only know about features and never look to plugins.

Therefore, a good practice is to have your core feature as a required package in your installer. Any other feature you would like the user to update through the update system should also be joined as a package in your installer. However, if you wish to offer the user the choice to install only one plugin regardless what is its feature, you can do it without further consequences. Your application will work without a problem and with this plugin activated.

So, you have decided what will be the packages available in your installer. You must know what license you'll use and you can have a couple shortcuts because it's always useful.

Now let's produce the XML file that will explain to IzPack how it should work.
Your first section of the IzPack XML should be the something like:

<info>
<appname>Your App</appname>
<appversion>@{version}</appversion>
<authors>
<author name="Tarantulus Corp." email="archimedesproject@googlegroups.com" />
</authors>
<url>http://www.archimedes.org.br/</url>
<webdir>http://arquimedes.sf.net/update</webdir>
</info>


No big secret on that. It defines mainly the first screen post language choose. Excepting 'webdir' all those fields are shown in that screen. The 'webdir' is the addressed used to search for the package if you are about to create an online installer. This is mainly the only thing that changes from a local installer to an online installer in IzPack.
The second part of your XML should be:

<guiprefs width="640" height="480" resizable="no">
<modifier key="useButtonIcons" value="yes" />
<modifier key="useLabelIcons" value="yes" />
<modifier key="langDisplayType" value="native" />
<modifier key="headingPanelCounter" value="progressbar" />
<modifier key="headingPanelCounterPos" value="inNavigationPanel" />
</guiprefs>

This is a bit more obscure. The first lines are quite easy to understand. 'landDisplayType' is not that easy however. It sets how the installer will show the options of language to the user on the first screen of your installer. In this case, native tells the software to use the system's locale to write the languages. 'headingPanelCounter' and 'headingPanelCounterPos' defines how the steps remaining and the current step should be shown to the user. If those lines are not present, nothing will be displayed.

Next you have:

<resources>
<res id="installer.langsel.img" src="installer.png" />
<res id="LicencePanel.licence" src="license.txt" />
<res id="shortcutSpec.xml" src="shortcutSpec.xml" />
<res id="packsLang.xml_eng" src="packsLang_eng.xml" />
</resources>


Okay. Now we're talking! First of all, the image to be shown in the first screen of the installer is the one on the first line. The license that will be displayed to the user and that he will be forced to accept unless it quites the install. Beware, this license should be in a text format because IzPack will display it as a text only file. The last lines regard the shortcut creation and the internationalization of this installer. Take a look on the official documentation and this should be enough.

The next part is what will define the flow of your IzPack installer:

<panels>
<panel classname="HelloPanel" />
<panel classname="LicencePanel" />
<panel classname="PacksPanel" />
<panel classname="TargetPanel" />
<panel classname="InstallPanel" />
<panel classname="ShortcutPanel" />
<panel classname="FinishPanel" />
</panels>

Those panels are available by default in IzPack. You can, however, create your own panels as well as install new ones created by the community and available mainly at IzPack's site (http://www.izforge.com/izpack).

At last, the last part is the most important one. The one that will specify each pack of your application:

<packs>
<pack name="Core" id="core" required="yes">
<description>The core of Your App.</description>
<fileset dir="@{deployDir}/win32.win32.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="startup.jar" />
<include name="configuration/config.ini" />
<include name="features/org.eclipse.rcp*/**/*" />
<include name="features/your.company.project.feature*/**/*" />
<include name="plugins/**/*" />
<exclude name="plugins/your.company.project.*.jar" />
<exclude name="plugins/org.eclipse.swt.*linux*.jar" />
<exclude name="plugins/org.eclipse.opengl.linux*/*" />
<exclude name="plugins/org.eclipse.opengl.linux*/**/*" />
</fileset>

<fileset dir="@{deployDir}/linux.gtk.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="icon.xpm" />
<include name="yourapp" />
<include name="about.html" />
<include name="libcairo-swt.so" />
<include name="about_files/**/*" />
<include name="plugins/org.eclipse.swt.*linux*.jar" />
<include name="plugins/org.eclipse.opengl.linux*/**/*" />
<os name="linux" />
</fileset>
<fileset dir="@{deployDir}/macosx.carbon.ppc/YourAppName/" targetdir="$INSTALL_PATH">
<include name="yourapp.app/**/*" />
<include name="plugins/org.eclipse.swt.*macos*.jar" />
<include name="plugins/org.eclipse.opengl.macos*/**/*" />
<os family="osx" />
</fileset>
<fileset dir="@{deployDir}/win32.win32.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="yourapp.exe" />
<include name="plugins/org.eclipse.swt.*win32*.jar" />
<include name="plugins/org.eclipse.opengl.win32*/**/*" />
<os family="windows" />
</fileset>

<!-- The windows scripts -->
<executable targetfile="$INSTALL_PATH/yourapp.exe" stage="never">
<os family="windows" />
</executable>

<!-- The Linux scripts -->
<executable targetfile="$INSTALL_PATH/yourapp" stage="never">
<os name="linux" />
</executable>
</pack>
</packs>


Each <pack> must have one or more files registered. Those can be added using the file tag (when you want to work with one specific file) or the fileset tag (when you want to work with folders) as shown. The fileset accepts both <include> and <exclude> tags which allows you to easily create exceptions in your folders. Also, all those tags accept <os> that will be interepreted as a mark to tell the installer on which OSs those files should be unpacked. This is mainly how you separate things. The first fileset defined in the example above is the one that grabs all non-OS specific files from the RCP. The next 3 filesets are used to select os specific files as the 'os' tag shows.

At last, the <executable> tag marks the file you target as executable. This means a double click or a command will try to run those files. This is required because the installer will zip all the files in jars and loose all kind of permissions over the file on install. So it needs to know which files should be diferent from the read and write permissions.

All this should allow you to create a simple multi platform installer for your eRCP application. Once this is done, you'll probably want to add the <locale> tag to add internationalization support to your installer and then you'll need to create some language specific XML with pack descriptions translations and everything else.

A last tip, beware to export all of your features and plugins when you are in Eclipse. You'll need all the files available on your deployDir to make the installer work well.

The next post will discuss about how to create all the application, the installer and transfer all to a website using one simple script. This allows a much quicker and constant deploy of your software to your users. Expect it done for saturday or sunday.

See you guys soon. Bye bye.

Saturday, February 24, 2007

How to export multi-platform?

Well,
I hope that after those last two posts, you are already capable of adding your classes to your project and growing it without any further problems. Once this is done, I also expect that you can export your project and run it outside of Eclipse with no headache. You choose your deploy directory (which I'll call $DEPLOY_DIR) and you can run your executable software at $DEPLOY_DIR/yourapp(.exe). If this is not the case, feel free to contact me either by email or posting a comment.

So, now that you have your development environment set up and you can run your software in your platform, you probably want to export it into other operating systems (OS). For now, you don't even have this option anywhere you can find it. If you search a bit through the internet you'll discover you need the RCP-Delta-Pack to do so. Very good... but where the hell is that pack? If you search around the RCP download you'll eventually find it although it's not really very well exposed.

The way to find the up to date version is:
http://www.eclipse.org/downloads/
Choose "Other downloads for ..."
Get down to "RCP SDK" and the last file is the RCP delta pack.
For the 3.2.2 version, just click here.

Now that you have your delta-pack, it's really easy. Just unzip the file into $ECLIPSE_HOME/plugins and restart your eclipse. Now when you ask to export your application, you'll get a nice checkbox asking if you want to export to multiple platforms. If you select it, the "next" button will become active and if you click it, you'll have a list of supported OSs. Let's say you'll select macosx_ppc, linux_x86 and win32_x86 (like Archimedes does).
The export system will use the $DEPLOY_DIR and create in it, 3 folders (one for each system):
linux.gtk.x86
macosx.carbon.ppc
win32.win32.x86
And each of these folders will contain all files needed to run the software on these OSs with those graphical interfaces.

If you take a look, you'll find that much is common to all OSs and we hope so, since it should be a platform-independent software. I cared to take a deeper look and list what is common and what is not.
Mainly, the "configuration" and "features" folder are identical. The "plugins" is mainly identical, the only thing that may change is a couple of plugin fragments that are OS specific (like "org.eclipse.opengl.linux" and "org.eclipse.open.macosx"). If the fragments have requirements regarding the OS, they will be selected only by the OSs that support that requirements. Careful about that! If you depend on a plugin that has a fragment like that one and it doesn't get exported, you'll get the friendly "There was an error. Please check .metadata/.log for more details." message. If you check the log, you'll find the also friendly (but known already) "No application ID found" message.

The root folder, however, is quite diferent depending on the OS you look. The only file that is always available is "startup.jar" which contains the basic RCP plugin system which will activate whatever needs to be activated.
All the rest is quite diferent. For example:
Windows has only a "yourapp.exe" file.
MacOS X has a whole folder "yourapp.app" with a nice deep structure required to make your software run like a native Mac software.
Linux is the most poluated one. It has "youricon.xpm", a folder "about_files" and a page "about.html", "libcairo-swt.so" and a "yourapp" executable file.

Now why is that important? Because you will probably want to make an installer (like Archimedes does) or a common package that would allow your users to download once the core and add the OS specific files as they need it. In this case, you'll need to know what is core and what is OS specific.

I'll stay here for today but my next post will be about creating this installer. I'll use IzPack (http://www.izforge.com/izpack) to make the example because it's what Archimedes uses and it is very simple and powerful. You can probably, however, use the example in any installer you'd like just adapting the procedure.

Thursday, February 22, 2007

Your first problems with RCP

Well,
Now that we had a good start with RCP, we face a couple of problems upgrading our application. First of all, if you are a curious person (and this is a good thing), you might be facing a couple of problems while trying to run your application from outside of Eclipse.

Problem number 1:
You can run your application from within Eclipse but when you try it outside of Eclipse you get a: "No class definition found ...".
If you are having this problem and the class that can't be found is one of your own, you probably made the wrong move! Check on your MANIFEST.MF file if you have a line: "Bundle-ClassPath:".
If you don't, you have gone even further that I though. Add it quickly!
If you have it, check that the path '.' is there. You MUST have '.' as a class path for your application or else none of your classes will be found.

Okay! That was easy to solve now that you found the solution.
You move along and you get challenged again:

You probably created your first RCP application with a product that was based on plug ins, right? Now it's time to move it to feature based architecture. Great! That will enable your application to benefit from the update features.
Go ahead! Change your product file to be feature based. Once you done that, all works perfectly within Eclipse but, again, when you run it outside, it does not works.

Problem number 2:
You can run your application from within Eclipse but when you try it outside of Eclipse you get a: "No application id found ...".

Okay! First thing to do, check the plug in folder from your application. It should contain all plug ins that are necessary to run you application. If one plug in is missing, you get the "No application id found ..." message.
If this does not help you, try opening the file "$YOUR_APP_HOME/workspace/.metadata/.log" with the Error log view in Eclipse. Take a look at the most recent entries. You should see the "No application id found ..." message and some warnings surrounding it.
Take a good look over the warnings looking for one of them that says something about "Bundles missing". It should be extensible. Extend it twice, you'll get a list of missing bundles. Those are the plug ins that the RCP is trying to load and is not finding. Search for errors within those plug ins or if they are available. Once they do, it should restart working once more.

Wonderful! So now you are feature based and your application works perfectly well inside and outside of Eclipse. Time to create an extension point for your application. Eclipse really helps for that. It creates all the necessary files for you and you can focus on whatever you want.

Problem number 3:
You want to define your extension point and you would like it to have children. Like in:

<extension-point id="myapp.myext">
<myext id="ext3">
<status name="fileSystem" />
<status name="swap" />
</myext>
</extension-point>

First of all, when creating your extension point, you'll find out that PDE 3.2 won't let you create a new definition within the extension point element. Don't worry! That's normal. It just doesn't create the xml tree at definition it understands when you use it. Second thing, just like the extension point, you can't create a new definition within your extension-point. Again, same procedure: ignore it and create it after your extension point definition but use it inside and all will go fine.

Now you have your extension points created. Time to create a new project that will extend this point. Go ahead! It's a good idea. So you start and once you done the whole thing you get a warning: "Illegal child element ..." at your "plugin.xml".
Well, my tip: Ignore it! It's a know bug from PDE 3.2 that is already fixed at the repository.

Well, those must be the first problems you'll face with RCP and probably the once you'll loose more time. After this, you understand the errors a bit faster and starts not getting stucked for stupid reasons like I did. :)

If you have other problems with or without solution, please post them and I'll do my best to help or to spread the solution a bit more.

Enjoy yourselves!

Saturday, February 17, 2007

Why Eclipse's RCP?

Well, let's start producing something interesting:
First of all, there are two things that you may be thinking of doing that will make you choose to work over Eclipse's Rich Client Platform (eRCP from now on):
  1. You want to develop a plug in for Eclipse. In such case, you have absolutely no choice. You will have to work over eRCP. On the other hand, you will be doing a lot of things that other persons already did and you will find several tutorials and samples that can help you.
  2. You want to develop a standalone application of your own. This will be the focus because it's doing this that you will find most problems.
Okay then, you want to develop your standalone application.
Why should or shouldn't you work over eRCP?

Mainly, what you will gain from working over eRCP is a very strong extensibility for your application with a great architecture as well as a very decent internal update system and a nice help system. Wow! Wonderful right? And there is more! If you start now, you get a "native" cross-platform application for free!

Ok! I got a bit too far with that last sentence. So let's keep cool, not all applications are meant to be developed using eRCP. So what are the counters?

You will spend some time learning how eRCP works. And when I say some time, I mean something like 3 or 4 days totally lost doing things you don't really understand how they work.
You will also have some megabytes inserted into your software even before you have anything working. To get an idea, if you use all the features I quoted before, before you have any code of your own, your application will already have some 16 Mbs. If your application is meant to be light weight, forget it!
At last, you will have to adapt to eRCP's architecture and believe when I say it: It's a very very good architecture but it forces you to achieve, at least, a very good architecture level. This may take you some considerable time (I'm still trying to reach it).

So, okay, when should I use eRCP than?
When you want to develop a pluggable application, flexible, very strong.
When you want/need a very good Internet update system.
Let's say the help system is a bonus because it is not that hard to do in any standalone application.

And when shouldn't I use it?
When you want things to go quickly, you have little time to do your little application.
When you don't need plug ins.
When you have limited memory or processing.

Okay! But you don't like IBM/Eclipse... is there an alternative?
Yes. Sun Microsystems has the Netbeans Rich Client Platform (nRCP). It has almost all the features eRCP has but you'll loose a bit of community support since it's much less widely used and you'll win good documentation because Sun manages to have some very competent documentation writers.

Now that we are set about what is Eclipse Rich Client Platform, I'll leave you some links where you can have more insights about it:
http://wiki.eclipse.org/index.php/Rich_Client_Platform (RCP's faq and official RCP's site)
http://www.eclipse.org/articles/Article-RCP-1/tutorial1.html (The first part of a trilogy article from Ed Burnette. Very useful to start with RCP)
http://www.eclipse.org/articles/Article-Branding/branding-your-application.html (an article to read after Burnette's one by Andrew Eidsness and Pascal Rapicault)
http://eclipsercp.org/book/ (The best book I found for eRCP though it's not free)

Of course you can find much more looking over the Internet for "Rich Client Platform Eclipse" or "Rich Client Platform Netbeans" or just "RCP your-topic".

The next step is to start developing your own RCP application from scratch but you'll have to wait until I'm back from the Brazilian Carnival for that. See you next week!

Thursday, February 15, 2007

Initial post

My name is Hugo and I'm a brazilian programmer but I'll write this blog in english for some reasons. The main reason for that is that I wish to share my programming and coding experience with as many people as possible. The second reason is that I really need to practice my writting in english (in other languages also but I'll handle that somewhere else).

I should have explained this earlier but this blog will be used to report several information about my programming experiences and problems faced. Most of my code is written in Java so you'll find a lot of infos about Java specificities and platforms available for it.

The main thing that drove me to start this is the lack of information there is about Eclipse's Rich Client Platform. I found several problem using it and I wanted to share those experiences. Another important part of this blog will be dedicated to Archimedes. I started this project almost 2 years ago (around july 2005) and I'll use this blog to give some infos from inside it's development.

This should be the main road although some things may come out of it from time to time. Of course, all comments and critics are welcome (even if it regards my crappy english spelling and grammar).