Interpreting DB2 JDBC error messages

On data migration projects using BD2, sometime there are some awkward DB2/JDBC errors.
It does not matter if it is DB2 on Windows, Unix or iSeries AS/400.

Part of the problem is that the error messages come in localized, on our case in Portuguese, making the debug task a lot harder since it’s almost impossible to find decent help by searching through the error messages. The other part of the problem is that the SQL error codes sometimes are unclear.
Here’s an example of a common problem that we have in data migration projects:

com.ibm.db2.jcc.b.rg: [jcc][t4][102][10040][3.50.152] Non-atomic batch failure. The batch was submitted, but at least one exception occurred
on an individual member of the batch.
Use getNextException() to retrieve the exceptions for specific batched elements.

com.ibm.db2.jcc.b.pm: Error for batch element #1: The current
transaction was rolled back because of error "-289".. SQLCODE=-1476,
SQLSTATE=40506, DRIVER=3.50.152

com.ibm.db2.jcc.b.SqlException: [jcc][103][10843][3.50.152]
[...] ERRORCODE=-4225, SQLSTATE=null

Following DB2 official documentation:

  • SQLCODE=-1476 means that the current transaction was rolled back because of one of the listed errors, but none of them made much sense since none of the errors identified seem to apply.
  • SQLSTATE=40506 means that the current transaction was rolled back because of an SQL error, which is basically the same as the SQLCODE above.
  • ERRORCODE=-4225 means an error occurred when data was sent to a server or received from a server, which is totally useless.

The real useful information is hidden in the second error message, in the ‘transaction was rolled back because of error “-289”‘ message. The key here is the -289 error.
This error means “Unable to allocate new pages in table space“, and this is the real cause for such a big fuss.

In data migration projects it’s common some of the DB2 table spaces to run out of space. But with such an error message, the error itself is kind of hidden in the middle of the stack trace, all that is shown is a loose error code…
For the sake of the developers productivity, the cause of the error should be highlighted and perfectly visible and understood in order to be quickly identified and fixed.

Timezone date and time conversion

Sometimes the dates and times are from different timezones and one needs to convert them into one’s own timezone.
To perform this in Java, one just has to get the original date and time in the original timezone and then format the obtained date and time in the required timezone.

Here’s a snippet explaining how to do convert a date and time from the GMT +1 timezone into the GMT timezone:

// Date and time
String dateTime = "2011-07-01 09:45:12";  

// GMT+1 date and time format definition
DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
df1.setTimeZone(TimeZone.getTimeZone("GMT+1"));

// Parses the date and time assuming it's in the GMT+1 timezone  
Date dateToConvert = df1.parse(dateTime);  
// Shows the original date and time in the GMT+1 timezone
System.out.println("  GMT+1 date and time: " + df1.format(dateToConvert));
     
// GMT date and time format definition
DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
df2.setTimeZone(TimeZone.getTimeZone("GMT"));  
   
// Converts the date and time in the final GMT timezone
System.out.println("One own date and time: " + df2.format(dateToConvert));

Find Java Class Path in the System

Many times one has to know where in the system some Java class is located, usually when one has to perform file operations relative to the class location.

In Java such task is not straight forward to accomplish. Here’s a snippet that will return the full path of the class location:

import java.security.CodeSource;
import java.security.ProtectionDomain;

public class Utilities {
 protected static final String getApplicationLocation() {

    final ProtectionDomain pd = Utilities.class.getProtectionDomain();
    final CodeSource cs = pd.getCodeSource();

    return cs.getLocation().getPath().replaceFirst("/", "");
 }
}

Selecting a value from a SWT CCombo on RCP

It looks like the CCombo custom SWT object lacks some selection functionality. When using a CCombo as a table cell editor on a Rich Client Platform (RCP) application, it is (almost) impossible to detect the user selection with both the keyboard and the mouse.

The selection listener does not work as expected. Documentation says:

  • the widgetSelected method is triggered whenever a selection occurs in the control, i.e. when the user browses the option list this event is triggered;
  • the widgetDefaultSelected method is triggered when default selection occurs in the control, i.e. when the user selects an option from the list this event is triggered.

One might think that all one has to do is to catch the widgetDefaultSelected event and one would know which option the user has selected from the list.
This is only true when the user performs the selection using the keyboard, i. e. after browsing through the options list the Enter/Return key is pressed.
If the user decides to use the mouse, the widgetDefaultSelected event is not triggered at all, but widgetSelected is.

One may though one could detect the user selection with the mouse listener. But it turns out there’s no (easy) way to detect if the user has performed a selection using the mouse…

Here’s a workaround for it. Since the widgetSelected is triggered by the mouse clicks, one may think in trying to use that event. Unfortunately the event has no real useful information, like if it was triggered by a right button mouse click. But fortunately, the CCombo object does have a couple of methods that allows to infer that a selection has been made. In particular, it has a method to check if the options list is visible or not. Since a selection with the mouse makes the options list disappear, one can use it.

Here’s a code snippet that does it:

// Selections events
combo.addSelectionListener(new SelectionAdapter() {
// Selection changed, check if the options are still visible
public void widgetSelected(SelectionEvent e) {
  // If list is not visible assume that the user has
  // performed selection with the mouse
  if (!combo.getListVisible()) {
      setEditionValue(combo);
  }
}

// Option selected
public void widgetDefaultSelected(SelectionEvent e) {
  // User performed a selection with the keyboard
  setEditionValue(combo);
}
});

This is not a perfect solution, it’s a workaround, but it’s a very helpful working solution.

SWT File Dialog

During the development of an Rich Client Platform (RCP) it is common to develop a file browse dialog, here’s how to show a file dialog in SWT:

import org.eclipse.swt.widgets.FileDialog;

FileDialog dialog = new FileDialog(this.getShell(), SWT.NULL);
dialog.setFilterExtensions(new String[] { "*.txt", "*.*" });
dialog.setFilterNames(new String[] { "Text files", "All files" });
String path = dialog.open();
if (path != null) {
   File file = new File(path);
   if (file.isFile()) {
     System.out.println(file.toString());
   }
}

The snippet above filters by text files (*.txt) and all files (*.*) and it is easily applied to the click event of any button or file menu option.

Intenationalize RCP applications

To internationalize (i18n) and Rich Client Platform (RCP) application, also known as Eclipse Application, it’s not enough to download the language package. One also needs to download the language packs for the RCP core.

Here’s what it takes to i18n the core of an RCP application:

  1. Download the language packages from the Babel project using the Eclipse install/update mechanism.
  2. Open the RCP application “.product” file.
  3. Go to the “Configuration” section.
  4. Press “Add Required Plug-ins” button.

This last step is the “magical step”, it includes the i18n plugins to the RCP application.
You can identify the language plugins by their name. They come in the “<plugin>.nl_<language>” format. For instance, Portuguese JFace translation file is “org.eclipse.jface.nl_pt”.

Install R on Kubuntu

Installing R on Kubuntu, or Ubuntu, with an editor is quite easy. The following steps will possibly work on the most common Linux distributions. Check the official information for more information.

To get R, start by updating the repositories and the get r-base:

$ sudo apt-get update
$ sudo apt-get install r-base

When one needs to develop a R package, the development stuff should also be installed:

$ sudo apt-get install r-base-dev r-recommended

As for an editor, one can use JGR. In order to use it, just follow the official installation under Linux.
JGR is Java based, so when there’s no Java installed, get it using:

$ sudo apt-get install sun-java6-jdk

To install JGR, it’s necessary to enable Java support in R:

$ sudo R CMD javareconf

And then install the JGR library:

$ sudo R
&gt; install.packages('JGR')

After installed, run:

&gt; library(JGR)
&gt; JGR()

JGR has a small problem though, it has been installed as root and it seems unusable with any other user. One can set the correct user permissions for that.

Automating the startup of R with JGR is simple when using a shell script. Name it runr.sh and include:

R -f /home/myUser/bin/jgr.r

While the jgr.r file contains the JGR start commands

library(JGR)
JGR()

Now, running ./runr.sh starts R and JGR all in one.

There are alternatives to JGR. Check Tinn-R and R Commander.