Validating a MSSQL database connection

Here is a very simple example for entering and validating a Microsoft SQL Server database connection (runnable as client on non-Windows OS also). Here are just the relevant parts without translations.

 

In the UserInputSpec.xml resource, define a panel containing the main input fields for a MSSQL database connection, containing several field validators to directly verify the user input of each single input field:

Resource userInputSpec.xml
<panel id="panel.mssql">
   <field id="panel.mssql.title" txt="Microsoft SQL Server Connection" type="title"/>
   <field type="text" variable="mssql.host">
      <spec id="panel.mssql.host" size="30" txt="DB host name:"/>
      <validator class="com.izforge.izpack.panels.userinput.validator.NotEmptyValidator" id="panel.mssql.host.error" txt="The host name must not be empty!"/>
   </field>
   <field type="space"/>
   <field type="rule" variable="mssql.port">
      <spec id="panel.mssql.port" layout="N:5:5" txt="Port:"/>
      <validator class="com.izforge.izpack.panels.userinput.validator.NotEmptyValidator" id="panel.mssql.port.error" txt="The port must not be empty!"/>
      <validator class="com.izforge.izpack.panels.userinput.validator.IsPortValidator" id="panel.mssql.port.error.invalid" txt="The port is invalid!"/>
   </field>
   <field type="space"/>
   <field type="divider"/>
   <field type="space"/>
   <field type="text" variable="mssql.user">
      <spec id="panel.mssql.user" size="20" txt="User name:"/>
      <validator class="com.izforge.izpack.panels.userinput.validator.RegularExpressionValidator" id="panel.mssql.user.error" txt="The user name is invalid!">
         <param name="pattern" value="[a-zA-Z0-9._-]+"/>
      </validator>
   </field>
   <field type="space"/>
   <field type="password" variable="mssql.password">
      <spec>
         <pwd id="panel.mssql.password" size="20" txt="Password:"/>
      </spec>
      <validator class="com.izforge.izpack.panels.userinput.validator.NotEmptyValidator" id="panel.mssql.password.error" txt="The password must not be empty!"/>
   </field>
</panel>

 

The installer descriptor contains elements like this containing a panel validator verifying the connection assembled from the values of all user input fields in summary if he/she presses Next:

 

install.xml
<resources
   <res id="userInputSpec.xml" src="@{izpack.build.directory}/userInputSpec.xml"/>
</resources>
...
<!-- Maven dependency after invoking dependency:properties in the POM -->
<jar src="@{net.sourceforge.jtds:jtds:jar}" stage="install"/>
<jar src="@{com.mysoft:validators:jar}" stage="install"/>
...
<panel classname="UserInputPanel" id="panel.mssql">
   <validator classname="com.mysoft.izpack.validators.MssqlConnectionValidator"/>
</panel>

 

Last but not least there is one custom panel validator MssqlConnectionValidator:
com/mysoft/izpack/validators/MssqlConnectionValidator.java
package com.mysoft.izpack.validators;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import com.izforge.izpack.api.data.InstallData;
import com.izforge.izpack.api.installer.DataValidator;

public class MssqlConnectionValidator implements DataValidator {

  private static final String STR_DEFAULT_ERROR_MESSAGE = "Cannot connect to the specified database.";

  protected InstallData installData;

  //Error and Warning Messages
  protected String str_errorMsg;
  protected String str_warningMsg = "";

  @Override
  public boolean getDefaultAnswer() {
    return true;
  }

  @Override
  public String getErrorMessageId() {
    if (str_errorMsg != null) {
      return str_errorMsg;
    } else {
      return STR_DEFAULT_ERROR_MESSAGE;
    }
  }

  @Override
  public String getWarningMessageId() {
    return str_warningMsg;
  }

  @Override
  public Status validateData(InstallData installData) {

    this.installData = installData;

    try {
      Class.forName(getDriver());
    } catch (ClassNotFoundException ex) {
      str_errorMsg = "Problem during loading db-driver.";
      return Status.ERROR;
    }

    //Test if Database is reachable
    try {
      Connection conn = null;
      conn = DriverManager.getConnection(getUrl(), getUser(), getPassword());
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(getQuery());
      rs.close();
      conn.close();
    } catch (Throwable ex) {
      str_errorMsg = "Could not connect to database: \n\n" + ex.getLocalizedMessage();
      return Status.ERROR;
    }

    return Status.OK;
  }

  public String getDriver()
  {
    return "net.sourceforge.jtds.jdbc.Driver";
  }

  public String getUrl()
  {
    StringBuffer url = new StringBuffer("jdbc:jtds:sqlserver://" + getHost());
    String port = getPort();
    String instance = getInstance();
    if (port != null && !port.isEmpty()) {
      url.append(":" + port);
    }
    if (instance != null && !instance.isEmpty()) {
      url.append(";instance=" + instance);
    }
    return url.toString();
  }

  public String getHost()
  {
    return installData.getVariable("mssql.host");
  }

  public String getPort()
  {
    return installData.getVariable("mssql.port");
  }

  public String getInstance()
  {
    return installData.getVariable("mssql.instance");
  }

  public String getQuery()
  {
    return "SELECT 1";
  }

  public String getUser()
  {
    return installData.getVariable("mssql.user");
  }

  public String getPassword()
  {
    return installData.getVariable("mssql.password");
  }
}

 

You must add the proper JDBC driver to the classpath/dependencies to get this compiled and running. For the above case it is the JTDS driver for MSSQL and Sybase