Tuesday, January 3, 2012

IzPack - A simple tutorial to create a JAVA based Installer

Hi friends, hereunder is the easy steps for creating the java installer (executable jars) using the IzPack.

Where to get IzPack

Download the IzPack distribution from http://get.izpack.org/izpack/4.3.5.
Prerequisite for IzPack is that you should have java installed in your host and path should be set to java/bin folder.

How to Install

If the native platform is windows, open the cmd client and type the following command for installation:
cd <download dir>
java -jar <downloaded IzPack jar>

If the native platform is linux, open the terminal and first navigate to download dir and launch the command for installing the IzPack.
cd <download dir>
java -jar <downloaded IzPack jar>

Follow the steps of installer it will install the IzPack on your host.

How to Use

IzPack having following component:
  1. install.xml : Used as a controller for all the installation process.
  2. userInputSpec.xml : Used for creating the installer panels.
  3. antActionSpec.xml : Used for calling different ant files based on the installation flow.
  4. RegistrySpec.xml : Used for registering the installed product to windows registry.
  5. ShortCutSpec.xml : Used for creating application shortcuts in program menu.
Sample Example

Assume you have a build file say build.xml which is responsible to create a war file for your deployment, you want to create a database in mysql and for that you have createdb.xml file. Now you need to create a installer which check the java version first, call the build.xml for creating your application war, copy your war to tomcat server and create database in mysql for you application along with automated uninstaller and program application registry for your application. Following code is a sample for doing these with help of IzPack :

Assumption

  1. build.xml : Build file for your project gives the final deploy-able application war.
  2. copyWar.xml: ant file having copyWar target which is responsible to copy the war file to selected server webapps directory.
  3. createDB.xml: ant file having createMySQLDB target which is having sql task to execute your database creation sql and needed the connector jar.
Steps for Creating Installer

Create a directory called MyInstaller inside your project say WatchEyeUI and follow these steps:
Project Structure for IzPack Installer



Step1: Configuring the install.xml

Create one xml file say install.xml and add the content like as:




    
        WatchEyeInstaller
        04012012
        
            
        
        http://www.mycompany.com
        1.6
    

    
  
  
    

    
        
    

    
    
    
    

    
        
    
 
  
 
 
        
    
    
        
    

    
        
        
        
            
        
    

    
    
        
        
        
        
        
        
               
    

    
        
        
        
    

    
    
        
        
        
        
             
        
        
        
        
        
    

    
 
        
            The set of base files.
            
            
            
        
        
            
        
       
           
        
        
           
        
    


Step2: Configuring the userInputSpec.xml

Create one xml file say userInputSpec.xml and add the content like as for creating the panel for taking the db parameter and server location:

       
            
               
            
            
            
               
            
                
                
            
               
            
                
                
            
               
            
                
                
            
               
            
                
                
                
                    
              
               
            
            
            
               
            
                
                
                                                                                                                                                                                                                   
Step3: Configuring the antActionSpec.xml

 
  
        
   
  
 
 
  
   
   
   
  
 
 
  
   
   
   
   
   
   
  
    

   Step4: Configuring the RegistrySpec.xml
     
           
  
  
   
   
   
   
       
   
        
  
  
  
    
             
  
 

  Step5: Configuring the ShortCutSpecSpec.xml
 
 
  
  
  
  
  
  
  
  
 
    Step6: Compiling the installer       Go to the bin directory of IzPack installation by following command:             cd C:\Program Files\IzPack\bin Use compile command to make the MyApplication.jar executable.Assume Project is in C:\WatchEye folder.
     compile C:\WatchEye\WatchEyeUI\installer\data\install.xml -b C:\WatchEye\WatchEyeUI\installer\data\ -o MyApplication.jar
It will create MyApplication.jar as executable. To launch the installer double click on your jar or type command java -jar MyApplication.jar for launching your installer.
References:
As per the request hereunder the sample createDB.xml file.
 
      
       
       
       
       
       
       
  
   
    
        
  
  
  
   
   
  
  
   
   
  
  
   
    
   
  
 
Sample: DBConnectionValidator class
package com.izforge.izpack.util;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.SQLException;
import com.izforge.izpack.installer.AutomatedInstallData;
import com.izforge.izpack.installer.DataValidator;

public class DBConnectionValidator implements DataValidator {  
 private String dbType="";
 private String cause="";
 @Override  
 public boolean getDefaultAnswer() {  
  return true;  
 }  

 @Override  
 public String getErrorMessageId() {  
  return "Can not connect to "+ dbType+" database." + cause;  
 }  

 @Override  
 public String getWarningMessageId() {  
  return "OPS-101";  
 }  

 @Override  
 public Status validateData(AutomatedInstallData arg) {  
  Connection connection = null;  
  try
  {
   URL urls [] = {};
   JarFileLoader cl = new JarFileLoader (urls);
   cl.addFile (arg.getVariable("jarFile.loc"));
   dbType=arg.getVariable("databasetype");
   java.sql.Driver driver=null;
   java.util.Properties props=null;

   System.out.println(arg.getVariable("jarFile.loc"));

   if(dbType.equalsIgnoreCase("MySQL")){
    Class cls = cl.loadClass ("com.mysql.jdbc.Driver");
    driver = (java.sql.Driver)cls.newInstance(); 
    props = new java.util.Properties();
    props.put("user", arg.getVariable("user"));
    props.put("password", arg.getVariable("password"));
    connection = driver.connect("jdbc:mysql://"+arg.getVariable("dbhostname")+":"+arg.getVariable("portno")+"/", props);
   }else if(dbType.equalsIgnoreCase("MS SQL Server")){
    Class cls = cl.loadClass ("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    driver = (java.sql.Driver)cls.newInstance(); 
    props = new java.util.Properties();
    props.put("user", arg.getVariable("user"));
    props.put("password", arg.getVariable("password"));
    // The replacement in the following is done to discard the % with \ while creating the connection URL with named instance.
    connection = driver.connect("jdbc:sqlserver://"+arg.getVariable("dbhostname").replace('%', '\\')+":"+arg.getVariable("portno"),props);
   }else if(dbType.equalsIgnoreCase("ORACLE")){
    Class cls = cl.loadClass ("oracle.jdbc.driver.OracleDriver");
    driver = (java.sql.Driver)cls.newInstance(); 
    props = new java.util.Properties();
    props.put("user", arg.getVariable("user"));
    props.put("password", arg.getVariable("password"));
    connection = driver.connect("jdbc:oracle:thin:@"+arg.getVariable("dbhostname")+":"+arg.getVariable("portno")+":"+arg.getVariable("instanceName"),props);
   }
  }
  catch (ClassNotFoundException e) {  
   e.printStackTrace();
   cause = "\nCause: Connector Jar is not valid for selected database!";
   if(dbType.equalsIgnoreCase("MySQL"))
    cause = cause + "\n\nYou can dowload the Connector Jar for MySQL form:\nhttp://dev.mysql.com/downloads/connector/j/5.0.html";
   else if (dbType.equalsIgnoreCase("MS SQL Server"))
    cause = cause + "\n\nYou can dowload the Connector Jar for MS SQL Server form:\nhttp://www.microsoft.com/download/en/details.aspx?displaylang=en&id=21599";
   else if (dbType.equalsIgnoreCase("ORACLE"))
    cause = cause + "\n\nYou can dowload the Connector Jar for Oracle form:\nhttp://www.oracle.com/technetwork/database/enterprise-edition/jdbc-10201-088211.html";
   cause = cause +"\n\nAfter selecting proper Connector Jar, proceed with the installation.";
   
   return Status.ERROR;  
  } catch (SQLException e) {  
   e.printStackTrace();
   cause = "\nCause: Invalid connection parameter(s) OR the database service is not started!";
   return Status.ERROR;  
  } catch (MalformedURLException e) {
   e.printStackTrace();
   return Status.ERROR;  
  } catch (InstantiationException e) {
   e.printStackTrace();
   return Status.ERROR;  
  } catch (IllegalAccessException e) {
   return Status.ERROR;  
  } finally {  
   if (connection != null) {  
    try {  
     connection.close();  
    } catch (SQLException e) {  
     return Status.ERROR;  
    }  
   }  
  }  
  return Status.OK;  
 }

 public static class JarFileLoader extends URLClassLoader
 {
  public JarFileLoader (URL[] urls)
  {
   super (new URL[]{});
  }

  public void addFile (String path) throws MalformedURLException
  {
   String urlPath = "jar:file:///" + path + "!/";
   addURL (new URL (urlPath));
  }
 }  
} 

37 comments:

  1. Replies
    1. createDB.xml is an Ant file which is useful for trigering the sqls need for your database creation, This file is not specific to IzPack build.

      Feel free to ask if you have any further query...

      Thanks,
      TechOSkelton

      Delete
    2. Can you please share a sample createDB.xml file. So I can use it as a reference. My mail ID-barathkrn6@gmail.com

      Delete
    3. Sure I will attach the sample in a day or two....as I am out of touch to my technical resources because of in-between journeys...

      Delete
    4. Ok, waiting for your reply...

      Delete
    5. As per the request I have added the createDB.xml which is used for creating database through calling the sql file.

      Delete
    6. How can I run sql queries as part of installer to fill initial data in the db?

      Delete
  2. I have one more doubt. Should we write a validator classes(ie NotEmptyValidator, DBConnectionValidator etc) or its already there in IzPack??? If it is already there in IzPack, where can I locate this???

    ReplyDelete
    Replies
    1. Some of the validator comes with the IzPack distribution but for some custom validation you need to write your own validator classes. DBConnectionValidator is a custom validator. Default validators can found in IzPack Instalation Directory\src\com\izforge\izpack\util.

      Delete
  3. I want to block the installation based on some condition failure.. Can You tell me how to do that.

    ReplyDelete
    Replies
    1. Abhinandan can you elaborate more as what does it mean that on condition failure block the installation.

      For example what I understand: If my installation process depends on some service and I am checking the condition that whether that service is running or not? And if it not running abort the installation process with error message that the service is not running. Than it can be done with IzPack.

      Delete
  4. I am checking the condition that whether the web service is running or not based on that i need to stop the installation . How to do that?

    ReplyDelete
    Replies
    1. Hi Abhinandan,

      How you are checking the condition, means is the condition is at process level or panel level.

      When I say panel level I mean that you need to enter webservice url in panel and than your validator class (custom validator) validate it whether the service is running or not? If that is the case you can return any error code from your validator with proper message and on click of OK installation process abort automatically.

      In other case, if it is on process level means through executable tag, you need to use failure attribute. If value is "abort" for "failure attribute", on executable target failure installer aborted.

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. hi,
      I am doing on the panel level can i get 5or10 lines of code for how to implement validator class.

      Delete
    2. I am updated the blog with Sample: DBConnectionValidator class for custom validator. It will validate the different parameters for db connection for MS SQL, MySQL and Oracle database.

      Delete
    3. Thank u for giving your precious time .

      Delete
  6. Hello. I see you have 2 user input panels defined in your install.xml file that reference different IDs in the single userInputSpec.xml file. But when I look at your userInputSpec.xml you only have one panel defined with one ID. Do you specify the second panel (with ID whereisserver) in the same userInputSpec.xml or? I have tried it like this and it won't compile so just wondering how you achieved it.
    Basically I need more than one user input panel, the second one depends upon the selection of the first.

    ReplyDelete
    Replies
    1. Also, sorry forgot to metion, nice tutorial in the first place, thanks.

      Delete
    2. OK I got it to work now. I had started the panel order at 1. When changing it to 0 it works. So now I have 2 panels like this:
      <userInput>
      <panel order="0" id="serverType">
      .....
      </panel>
      <panel order="1" id="serverDetails">
      .....
      </panel>

      In your example you start the index of the ID at 1.
      Thanks again for a great tutorial.
      cheers

      Delete
    3. Hi Martin,

      Sorry for late reply. I think you got your answer :). Feel free to ask if you have any other query.

      Delete
  7. Hello, Thanks for good article. I need to create installer for my web application which run on tomcat server. and also install jdk if it is not installed.

    I try your article and also try complie install.xml it giving me below error message.
    ----------------------------------------------------------

    Resource not found: .\data\JbpmCustomWorkItemDemo.war

    ---------------------------------------------

    Also it will better if i can it source code for project you display in screenshot(only IzPack part)

    Thanks in Advance
    Regards,Vishal

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Hi Vishal,

    The error what you have mentioned here is only occur if the Izpack is not able to find the given resource.

    For example if you see the first install.xml line no:97 the pack section:
    This will used to move the src dir or file to targetDir.
    Example:

    <file src="Installer Resource/custom" targetdir="${INSTALL_PATH}"/>

    In this case custom folder is copied to the Install path.

    Remark : we need to give src path relative to the install.xml file.
    So in my case custom folder is inside the Installer Resource and Installer Resource dir and install.xml is in same directory.

    Feel free to ask if you have any further query.

    ReplyDelete
  10. Hi Nick,

    I would like to create log file for IzPack installation process.
    How I can create it?

    Thanks,
    Alex

    ReplyDelete
  11. Hi Alex,

    Its there in install.xml line no 70.
    So for logging the installer log you need to use the in-build variable like:

    <variable name="InstallerFrame.logfilePath" value="$INSTALL_PATH/logs/installSummary.log"/>

    in your install.xml, where value is the path of log file.

    I think this is helpful for your query.

    Thanks.

    ReplyDelete
  12. Hello Nick
    i need some help please

    ReplyDelete
    Replies
    1. Yes, please post your problem....

      Delete
    2. I got an error while installation....

      "target createMySQLDB doesnot exist in the project DatabaseCreation"

      Delete
  13. Hello Sir,
    Do i have to create DBConnectionValidator class to validate database....

    If yes then where ????

    ReplyDelete
    Replies
    1. And one more thing when i trying to create DBConnectionValidator and extending DataValidator to it.............

      the problem is that i am using izpack5.0 and when i expore it, it doesnt have that class datavalidator in it

      Delete
    2. Well you can have your own validator like you have mentioned, Thing is you need to compile the validator with your own build and Izpack libs in 5.0, after that you need to specify the validator in your user input spec.

      Delete
  14. Nice example!!! I was looking something like that! but, I had problems with the ant task execution, seams like is never executed. What I am doing wrong? I looks so simple!

    ReplyDelete
  15. Please be sure that you have these jars in your package while compiling the installer :
    ant.jar, ant-launcher.jar, ant-apache-regexp.jar, ant-nodeps.jar.

    Also please verify that the target is correct in AntActionSpec.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  16. The user input fields are not aligned(start position of the fields are not the same) when combination of text and file type fields are used as given in your sample. I am unable to rectify this. Can you help?

    ReplyDelete
  17. Hi Nick,

    I would like to create Userinput pannel installation process.
    How I can create it?And i need to get the some data from who are all installing the project.Please give some suggestion..


    Thanks,

    ReplyDelete