Wiki News Projects Sources Tasks New Task Reports
Windows Installer For WAR
Page Info Get as PDF

Windows Installer For WAR

Top Announcement: 10-August-2008 EmForge-0.25 with Windows Installer released! See News for details.

Why Windows Installer?

So, after long time of development, your java-based web-application is ready and you want to give it to other people. What is the most common way to distribute web-applications? Yes, WAR-file. I agree with you. But I'm, as well as you - java-developer, and I know what to do with this WAR-file. But, you will be surprised with fact, that 99,9% of people in internet do not know what words "deploy" and "servlet-container" means! Really strange, but it is so (ok, probably not 99,9% but 99,8%, but still, a lot).

Of course it depends from audience, you want your application will be used. If it is same java-developers, your WAR-file (or just sources with instruction how to build) will be quite OK. But if you want your application will be used by many "simple" users - you need something more simple.

Since most people still (another strange fact - why?) used Windows, most comfortable way to install applications is Windows Installer, and here I will try to explain my simple experience in making installer for java-based web-application.

Ajax Based File Upload

From WAR to Launcher.

Our first step - to make "launcher". Distributing WAR-file supposed, what user already has some server installed. But, to avoid users to find, install and configure server just to try your application, we should include some into our "distribution". In our example we will use Jetty, but I'm sure it is also possible to do the same with Tomcat, or any other server.

Since in my case I'm using maven as build-system, followed way is used maven too. If you do not use maven - you can simple skip this step - just download jetty and make same folder structure as will be explained at the end of this step

Building Jetty Launcher with Maven

Followed receipt I've got from Harlan's blog. I will not stop a lot on this step - just will explain general idea:
  1. we have maven-based web-project (http://www.emforge.org/browser/EmForge/trunk/emforge-web in my case)
  2. making new project - emforge-launcher (http://www.emforge.org/browser/EmForge/trunk/emforge-launcher)
  3. configure maven assembly plugin to get Jetty libraries and placing them into right places
  4. first, run mvn clean install for web-project, to put it into local maven repository
  5. then run mvn clean assembly:assembly in launcher project to get zip with project, bundled with Jetty.

As result we will have zip in our target folder (for example EmForge-0.25-SNAPSHOT.zip) with ready to use jetty server, included your web-application. It is already a little bit better and simpler for end-user comparing to just WAR, so, you can stop at this point. If you want ot build MSI file from it - lets go!

Note: To make same for your project feel free to get emforge-launcher from subversion repository: http://svn.emforge.org/svn/emforge/EmForge/trunk/emforge-launcher/ and replace all required strings with name of your project.

To continue - we need to unzip result ZIP into some folder

Result Folder Structure

Does not make sense - used we maven or not, we should receive followed directory structure somewhere:

- etc                          Folder with jetty configs
   - jetty.xml
   - jetty-win32-service.xml
   - webdefault.xml
- lib                          Folder with libraries, required to start Jetty
   - wrapper.dll
   - wrapper-3.2.0.jar
   - jety-6.1.11.jar
   - jetty-util-6.1.11.jar
   - jetty-win32-service-java-6.1.11.jar
   - servlet-api-2.5-6.1.11.jar
   - start-6.1.11.jar
-logs                           Placeholder for logs
- webapps                       
   - root                       Under this folder your web-application should be placed

Jetty-Service.exe               Exe-file to start Jetty as Service
jetty-service.conf              Config
Please, check:
  • jetty-service.conf should be configured to use your name of Service (you can keep Jetty, but probably it is better to run service with name of your Application)
  • also check jetty-service.conf what correct paths to logs and libs is configured
  • Check the port, configured to use in jetty.xml - by default it is 8080, but it may be already used by some other server. In my case I configured Jetty to use 9191
  • folder root should contain your web-applucation, so, for example, it should contain WEB-INF folder, your jsps and so on.

Alternatives to wix

Before we will discuss the wix, I would like to stop on two alternatives I found:

WItem Installer for Java

Here: http://www.witemsoft.com/forjava/ you can find quite simple & free program allowed to make installer for web-application. You just point it to your web-app, and say 'it is web-application'. It will make windows installer package (MSI) with bundled jetty configured to run your application.

Very easy and simple! Unfortunately it is used Jetty 4.x and I do not found a way how to configure it to use some newer version of Jetty. So, I was not able to use it in my case.

Advanced Installer for Java

http://www.advancedinstaller.com/java.html - a little bit more complex but much more powerful. With quite comfortable wizards allow you to create installation. It has no bundled Jetty, so, you will have to use our previously prepared package. It has many features (like checking for Java-version installed, automatic download and install java if required and so on), but, unfortunately, feature allowed you to create and configure services (simplest I needed) included only starting from "Professional" version and cost from $249 (Java-edition cost from $299). If you have $250 in you pocket - feel free to use this application - I'm sure - even if you do not know how Windows Installer is working you will able to create installation for your webapp in 2 hours (also - trial version is available)

I did not want to spend $250 only for automatic configuring windows services, so, tried to use wix - lets speak about it a little bit

WIX to make installation

First of all a little bit about WiX. WiX is a open-source project from Microsoft. Yes, yes, it is not a joke! Not only Sun opened own product (ok, comparing to Sun I cannot say WiX is a key product from Microsoft) - Microsoft opened sources for Wix many years ago and placed them into SourceForge (wow - imagine Windows sources hosted by SF!) and now this product supported by community.

Major links are:

To use Wix you will need download it from SourceForge (I used version 2.x) . Since WiX written in .NET you will need download and install .NET Framework from Microsoft (sorry, my java-friends, for WiX we will have to do it)

Requirements For Installation

Before we will write our installation lets discuss that we are waiting from it:
  • First of all - installing our files into system;
  • Allow user to configure folder there application will be installed
  • Configuring Jetty as Service to automatic start
  • Start Service after installation
  • Create Link to our web-application on Desktop and Program Files
  • Correctly remove everything during uninstall

Of course I would like to check for java-version installed, configure port used and so on and so on... but seems in next version.

First WiX file

WiX is building Windows Installer packages from xml-based sources, so, to make installation we will need to have only xml-editor (I used Eclipse) and command-line to run WiX commands.

Lets Write initial Wix-File (emforge.wxs in my case)


<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
    <Product Id='????????-????-????-????-????????????' Name='EmForge' Language='1033'
            Version='0.24.0.0' Manufacturer='EmDev Limited'>
        <Package Id='????????-????-????-????-????????????'
                Description='EmForge Installer'
                Comments='EmForge Server Installer'
                InstallerVersion='200' Compressed='yes' />

        <Media Id='1' Cabinet='emforge.cab' EmbedCab='yes' />
        
         <Directory Id='TARGETDIR' Name='SourceDir'>
         
           <Directory Id='ProgramMenuFolder' Name='PMenu' LongName='Programs'>
        	<Directory Id='ProgramMenuDir' Name='EmForge'/>
      	   </Directory>

      	   <Directory Id='DesktopFolder' Name='Desktop' />
      
           <Directory Id='ProgramFilesFolder' Name='PFiles'>
         </Directory>
    </Product>
</Wix>

Currently is it not real installation - it just contain some general info: change names to name of your product, also, please, replace all ? with real GUID's (for example generated by this program ). Each GUID should be unique!

It specify Product & Directories what will be used: top-level TARGETDIR, creates "EmForge" folder in "Start -> All Programs" menu, specify Desktop Folder and specify "Program Files" folder there we will place our application

JAR-ing your classes

A little bit later you will see, WiX (as Windows Installer in general) has quite "strange" way to work with folders, so, as less folders your application will have, as better. Plus, moving your folders may have dramatical results for your installation, specified in WiX, so, I'm recommending you to jar your classes and place result jar into libs (with removing contents of all WEB-INF/classes folder). As for me - I just do not want ot think how some refactoring step related to renaming package will affect my installation. Really do not want to think about it!

In most cases this operation should be "safe" - your classes and resources still will be in classpath - but... still it make sense to test application again - is everything working well.

Dancing with Folders

Now, we need to include into installation information about files we want to include into our installation. Quite easy step (what may be simpler - just pointed folder and said - "This is what I want to see in my installation!") not so trivial in WiX. I think this complexity grows from way, how Windows Installer process folders. As I understand - installation itself contains from many components (we will see them later), and each component may have several files, BUT NOT FOLDERS. So, we should specify component for each folder.

Hopefully, WiX simplified this work a little bit. Call


# PathToWix\tallow -d c:\Path\To\Your\Distro > tallow.wxs
Where:
  • PathToWix - path there wix is installed
  • c:\Path\To\Your\Distro - path to your distribution (it structure were discussed a little bit earlier)

As result you will receive file with description of files, will be included into distribution (my example you can see here). Now, you need to get GUIDGEN program pointed before and replate all PUT_GUID_HERE with real GUID's. (It is why I recommended to reduce number of folders by Jar-ing classes)

After you will do it, copy whole contents under tag DirectoryRef (not including DirectoryRef itself) and paste it inside your "ProgramFilesFolder" in wxs file we started create before.

OK, we created Folder "EmForge" under "Program Files" and it will contain all required files.

Specify feature

Now, we need specify Feature installed (we will have only one feature, but more complex installation may have several: program itself, documentation, tutorial, examples and so on. Insert after all Directories (under Product tag)

      <Feature Id='EmForgeFeature' 
      		   Title='EmForge Server' 
      		   Level='1'
      		   ConfigurableDirectory='INSTALLDIR'>
         <ComponentRef Id='component0' />
         <ComponentRef Id='component1' />
         <ComponentRef Id='component2' />
         <ComponentRef Id='component3' />
         <ComponentRef Id='component4' />
         <ComponentRef Id='component5' />
         <ComponentRef Id='component6' />
         <ComponentRef Id='component7' />
         <ComponentRef Id='component8' />
         <ComponentRef Id='component9' />
         <ComponentRef Id='component10' />
         <ComponentRef Id='component11' />
         <ComponentRef Id='component12' />
         <ComponentRef Id='component13' />
         <ComponentRef Id='component14' />
      </Feature>

Hm... actually - initial installation is ready! Build it:


# candle emforge.wxs
# light -out EmForge.msi emforge.wixobj
and double-click EmForge.msi. "Silent" installation - no any messages will be displayed should be performed. As result you will see content of you web-app distribution under "c:\Program Files\EmForge" (or any other name you selected). After uninstalling - everything will be removed

Tuning Folders, creating service and shortcuts

In installed folders you will see one small problem: logs folder will be missed (since it was empty - Wix is not included it into installation). To avoid this problem add it like this:

        <Directory Id="directoryLogs" Name="logs">
        	<Component Id="componentLogs" DiskId="1" Guid="????????-????-????-????-????????????">
        		<CreateFolder />
        	</Component>
        </Directory>

Later, we will want to configure the path, there application should be installed. To make it a little bit easier, rename id of our root folder under "Program Files" to INSTALLDIR:


...
         <Directory Id='ProgramFilesFolder' Name='PFiles'>
            <Directory Id='INSTALLDIR' Name='EmForge'>
...

Now, we want to configure service and shortcuts. To do it - move Jetty-Service.exe into separate component and add some extras to it:


...
        <Component Id="component0" DiskId="1" Guid="26C1DEF2-6DDD-4b61-A4AC-C03E9AAAA96F">
          <File Id="file0" Name="JETTY-_1.CON" LongName="jetty-service.conf" Source="D:\work\EmForge\trunk\emforge-launcher\target\EmForge\jetty-service.conf" />
        </Component>
        <Component Id="EmForgeServiceComponent" DiskId="1" Guid="4E28D7D9-93E9-402f-B3AA-22B31F1CFEC1">  
          <File Id="file1" Name="JETTY-_1.EXE" LongName="Jetty-Service.exe" Source="D:\work\EmForge\trunk\emforge-launcher\target\EmForge\Jetty-Service.exe" />
          
          <ServiceInstall Id='EmForgeServiceInstall' DisplayName='EmForge Server' Name='EmForge'
          					Arguments='-s "[INSTALLDIR]jetty-service.conf"'
    						ErrorControl='normal' Start='auto' Type='ownProcess' Vital='yes' />

          <ServiceControl Id='EmForgeServiceControl' Name='EmForge'
    			Start='install' Stop='uninstall' Remove='uninstall' />
    			
          <IniFile Id="URL" Name="EmForge.url" Directory="ProgramMenuDir" Section="InternetShortcut" Key="URL" Value="http://localhost:9191" Action="addLine" />
          <IniFile Id="URL_1" Name="EmForge.url" Directory="DesktopFolder" Section="InternetShortcut" Key="URL" Value="http://localhost:9191" Action="addLine" />
          <IniFile Id="URL_2" Name="EmForge.url" Directory="FavoritesFolder" Section="InternetShortcut" Key="URL" Value="http://localhost:9191" Action="addLine" />
    			
        </Component>
...

I hope it quite trivial:

  • ServiceInstall tag added service and specified some of it's properties (for example command line arguments used - here we using property INSTALLDIR what will contain path to the installation folder)
  • ServiceControl said that to do with this service during installation and uninstallation the program (start on installation, stop & uninstall on uninstallation)
  • 3 ini-files creates URL to http://localhost:9191 (since our application configured to use port 9191) on Desktop, in Programs Menu and in Favorites.

Fix Feature to include new components:


...
      <Feature Id='EmForgeFeature' 
      		   Title='EmForge Server' 
      		   Level='1'
      		   ConfigurableDirectory='INSTALLDIR'>
         <ComponentRef Id='component0' />
         <ComponentRef Id='componentLogs' />
         <ComponentRef Id='EmForgeServiceComponent' />
         <ComponentRef Id='component1' />
...

Try to build and run installation again. With still silent installation you should receive everything working - service should be installed and started, links created.

Adding some GUI

Now lets to add some GUI. Simple add

...
      </Feature>

      <Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
      <UIRef Id="WixUI_InstallDir" />
</Product>
...
at the end and change your build:

# candle EmForge.wxs
# light -out EmForge.msi EmForge.wixobj PathToWix\wixui.wixlib -loc PathToWix\WixUI_en-us.wxl

Run EmForge.msi - now installation should not be so "silent" - it will allow you to choose the folder and display some extra info about installation progress!

License

Ah yes, of course you will like to change license text with some of yours. Simple place file License.rtf in same folder there wxs file and run build again. Now, correct text should be displayed.

Result

So, I cannot say Windows Installer package received during this steps is full-functional, but still, I think it is more easy for "simple" users to install your web-app by simple clicking on MSI instead of "deploying" WAR file.

In total it should not take more then 2-3 hours, so, I hope this time cost these results.

If you need, whole source of EmForge installer is available via SVN: http://svn.emforge.org/svn/emforge/EmForge/trunk/emforge-launcher/src/main/wix/emforge.wxs - feel free to use it as start-point for your own installer.

Sometimes later I will try to improve installer by adding more "product-specific" texts into installation, optimizing working with folders (seems WiX 3.0 has some better features for this), configuring port and so on and so on.

If you have any comments or suggestions feel free to leave them here, or in our EmForgeMailLists on in SourceForge forum

Last Modified by akakunin 3 months ago
Comments (0)
Login to add comment
Attachments (1)

installation.png