Java Serializable and serialVersionUID

January 14th, 2010 by nils

Here’s a question:

Is a serialVerionUID required on abstract classes?

My first thought: No way! If the serialVersionUID is used by the serialization mechanism to check whether some serialized data is compatible with a serializable class, abstract classes (that will never be instantiated, and thus, never be serialized directly) don’t need one! The problem is that the entire inheritance tree is checked when a class is de-serialized — and that includes abstract base classes. A simple example illustrates the problem:

If we have an abstract base class …

import java.io.Serializable;

public abstract class Base
implements Serializable {}

… and a sub-class that declares a serialVersionUID …

public class Sub extends Base {
    private static final long serialVersionUID =
      -7913545780181427623L;
}

… and we create an instance of the sub-class and serialize it to a file …

...
Sub sub1 = new Sub();
try {
    FileOutputStream fout = new FileOutputStream("sub.dat");
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(sub1);
    oos.close();
} catch (Exception e) {
    e.printStackTrace();
}

… and then we change the base class by e.g. adding an int field …

import java.io.Serializable;

public abstract class Base
implements Serializable {
    int a = 0;
}

… and try to de-serialize the sub-class …

Sub sub2 = null;
// Load the file and de-serialize the object
try {
    FileInputStream fin = new FileInputStream("sub.dat");
    ObjectInputStream ois = new ObjectInputStream(fin);
    sub2 = (Sub) ois.readObject();
    ois.close();
} catch (Exception e) {
    e.printStackTrace();
}

… we’ll get a “java.io.InvalidClassException”.

If we do the same thing, but define a serialVersionUID in the abstract base class, the exception would not occur. The reason for this is, that if a serialVersionUID is not explicitly declared, the JVM will calculate a default one, “based on various aspects of the class” [1]. This is a great mechanism, at first glance it even seems to be better than creating the id manually — if the class changes, these changes are automatically reflected in the generated id. But, this mechanism can differ based on the VM If you would run this example on one VM and then try to de-serialize the same “sub.dat” file with a different VM, without modifying the base class, it is possible that you would get an “InvalidClassException”, simply because the VM uses a different mechanism to calculate the default serialVersionUID. This is why it is recommended to manually declare the serialVersionUID.

However, this also means that, if we change a serializable class and thereby make it incompatible with previously serialized instances, we have to update the serialVersionUID!

Now if we think about software maintenance and data integrity, there should be a way to migrate existing serialized data to new versions of the serializable class. I’d be interested to know if there is an official recommendation for this, but didn’t investigate further yet.

It would also be interesting to see how OR-mapping frameworks fit into the picture. There is an interesting thread on using Serializable and what to do with the serialVersionUID in the hibernate JIRA: http://opensource.atlassian.com/projects/hibernate/browse/HBX-964

I’d be interested to know what others think about this, so please feel free to comment!

[1] http://java.sun.com/javase/6/docs/api/java/io/Serializable.html

jBPM 4.3 and Spring

January 6th, 2010 by nils

jBPM has just been released in version 4.3 and the spring integration has been changed. If you used to have an application that uses the spring integration of previous versions of jBPM, this might lead to exceptions like this:

org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'repositoryService': Requested bean
is currently in creation: Is there an unresolvable circular
reference?

The problem is that rather than having to declare all of jBPM’s services in your application context — like it used to be up to jBPM 4.2 —, the new spring integration provides access to them through the Process Engine. All you need in your application context is this:

<bean id="springHelper">
  <property name="jbpmCfg" value="PATH TO YOUR jbpm.cfg.xml">
</property>
</bean>
<bean id="processEngine" factory-bean="springHelper"
factory-method="createProcessEngine" />

Now you can inject the processEngine into your classes and retrieve jBPM’s services like this:

processEngine.getExecutionService() …
processEngine.getRepositoryService() …
…

Eclipse on Snow Leopard (10.6.2)

November 24th, 2009 by nils

When I downloaded and installed Eclipse (eclipse-SDK-3.5.1-macosx-carbon.tar.gz) yesterday, I started to get the following error message:

eclipse-update-error

Eclipse error message: "Cannot complete the request. This installation has not been configured properly for software updates!"

To fix this, you need to go to “Preferences > General > Capabilities” and check “Classic Update”. Afterwards you should be able to select “Help > Software Updates > Find and Install…”.

I wasn’t able to find much on the internet, but this post on an Ubuntu forum finally brought the solution.

Some pictures form our New England trip

October 5th, 2009 by nils

Technology…

October 2nd, 2009 by nils

Just came across this Lawrence Lessig quote in a really interesting article on sketching in hardware:

Technology is responsible for bringing us back from a Read Only (RO) culture to a Read-Write (RW) one…Human beings have been RW during most of our history. But for some time we stopped creating things and started consuming them instead.

So I decided to switch to read-write mode, post this here, and maybe give you some food for thought for the weekend…

Maven Dependency Conflicts

September 24th, 2009 by nils

Have you ever seen an exception like this:

org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'XY' defined in class path resource
[applicationContext.xml]: Instantiation of bean failed; nested
exception is org.springframework.beans.
BeanInstantiationException: Could not instantiate bean class
[XY]: Constructor threw exception; nested exception is
java.lang.LinkageError: You are trying to run JAXB 2.0 runtime
(from jar:file:/.../WEB-INF/lib/jaxb-impl-2.1.8.jar!/com/sun/
xml/bind/v2/model/impl/ModelBuilder.class)but you have old
JAXB 1.0 runtime earlier in the classpath (at jar:file:
/.../WEB-INF/lib/jaxb-impl-1.0.4.jar!/com/sun/xml/bind/
WhiteSpaceProcessor.class) Please remove the JAXB 1.0
runtime for 2.0 runtime to work correctly.

Well, I have, several times… and the task of having to figure out which library causes this dependency conflict seemed unresolvable pretty scary at first! Luckily, there is the m2eclipse plug-in with its excellent dependency graph. So if you are using Eclipse, whether you are actually using m2eclipse to manage your project or not, just the dependency graph makes it worth having a look at it. I still run my maven tasks on the command line, but have m2eclipse installed, just to be able to use the graph.

Dependency Graph

After identifying which library is causing the dependency conflict, all you have to do is to add an “exclude” node to that dependency in your pom.xml. In the above case, this snipped did the trick:

<dependency>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
    <exclusions>
        <exclusion>
            <artifactId>jaxb-impl</artifactId>
            <groupId>javax.xml</groupId>
        </exclusion>
        ...
    </exclusions>
</dependency>

Java and Snow Leopard

September 22nd, 2009 by nils

I noticed that there isn’t a whole lot of useful information about Java and Snow Leopard (OS X 10.6) out there on the web. Maybe this is because there isn’t a whole lot to say about it. Snow Leopard comes with Java 6 (1.6.0_15 that is) only, which means that the links that still exist in the

/System/Library/Frameworks/JavaVM.framework/Versions/

directory all point to “CurrentJDK”, which points to “1.6″. The thing is that Snow Leopard ships with a 32 bit version and a 64 bit version of the VM (Virtual Machine), 64 bit being the default one. The Java Preferences app shows this nicely:

Java Preferences Application

And that is the big news about it, since a 32 bit version of java 6 didn’t previously exist for OS X.

Now I’ve previously had to tweak Eclipse to use the 1.5 VM (see “Java Versions on Mac OS X“), and now it just works. I’m assuming that this is because of the “mixed mode”:

$ java -version
java version "1.6.0_15"
Java(TM) SE Runtime Environment (build 1.6.0_15-b03-219)
Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02-90, mixed mode)

…so the VM would automatically detect if an application should be executed in 64 or 32 bit mode and then start the correct VM. I still need to investigate how this actually works. Anyway, the good news is that java and eclipse seems to be working better with Snow Leopard. I’ll write more on this as I continue working with it, for now here is an interesting post on the topic:

http://blog.zvikico.com/2009/09/eclipse-java-and-snow-leopard.html

Find out which applications are listening to which port on Mac OSX

September 11th, 2009 by nils

If you ever wonder which ports are open on your OS X machine, or whether e.g. jboss is still running, this command will help you:

$sudo lsof -Pi | grep -i "listen"

FAQ: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ
Man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man

Different Maven Versions on OS X

April 24th, 2009 by nils

I keep running into the problem that different projects I’m working on require different versions of maven. I have two versions installed, maven 2.0.6 in /usr/share/maven-2.0.6 and maven 2.0.9 in /usr/share/maven. To find out which version of maven you are running, open a terminal and type the following

$ mvn --version
Maven version: 2.0.9
Java version: 1.6.0_07
OS name: "mac os x" version: "10.5.6" arch: "x86_64" Family: "mac"

In this case, maven 2.0.9 is running, so we’ll see how to switch to maven 2.0.6. First we need to know where the maven executable, or in this case, the symbolic link to the executable is located:

$ which mvn
/usr/bin/mvn

Next, we’ll use ls to check where the symbolic link is pointing:

$ ls -l /usr/bin/mvn
lrwxr-xr-x  1 root  wheel  24 Apr 24 14:26 /usr/bin/mvn -> /usr/share/maven/bin/mvn

Finally, if you have different maven versions installed, you can switch between them by overwriting the symbolic link:

$ sudo ln -fhsv /usr/share/maven-2.0.6/bin/mvn /usr/bin/mvn

After providing your password, the symbolic link should now be pointing to the maven 2.0.6 executable. To doublecheck, type

$ mvn --version

The output should be something like this

Maven version: 2.0.6

Compiling and Installing mod_auth_mysql on OS X 10.5.6

April 17th, 2009 by nils

The apche module mod_auth_mysql makes it possible to use a MySQL database instead of e.g. a passwd file. There is an installer of the module for Mac OS X 10.4, but no installation package or port for Mac OS X 10.5 or later. I played around with the sources a little bit and finally managed to get it to compile and apache to start without error messages. I’ve created a diff file to patch mod_auth_mysql.c. The following steps explain how to apply the patch, compile the module and test your apache configuration.

We’ll first create a src folder in your user directory, download mod_auth_mysql and expand it:

$ mkdir ~/src
$ cd ~/src
$ curl -O http://puzzle.dl.sourceforge.net/sourceforge/\
modauthmysql/mod_auth_mysql-3.0.0.tar.gz
$ tar zxvf mod_auth_mysql-3.0.0.tar.gz

Now you have the sources of the module in the folder mod_auth_mysql-3.0.0. Before we can compile it, the patch has to be applied. Here is the diff file mod_auth_mysql, save it to

~/src/mod_auth_mysql-3.0.0/mod_auth_mysql.diff

To apply the patch, we change to the sources directory and execute the unix patch program that takes the original file and applies the diff file as patch:

$ cd mod_auth_mysql-3.0.0
$ patch mod_auth_mysql.c mod_auth_mysql.diff

Now we are ready to compile the module, install it and add it to http.conf, the apache configuration file. Apache modules are compiled using apxs, the APache eXtenSion tool. Before we start, lets look at the command:

$ sudo apxs -c -i -a -D lmysqlclient -lm -lz \
-I/usr/local/mysql/include/mysql/\
-L/usr/local/mysql/lib/ -Wc,"-arch x86_64" \
-Wl,"-arch x86_64" mod_auth_mysql.c

We should execute apxs as super user because it will attempt to install the module to /usr/libexec/apache2/, so we prepend the command with sudo. the -c option tells apxs to compile the module, -i to install it and -a to add a line to http.conf, telling apache to load the module. The -I and -L options are used to provide information about where MySQL is installed and where to find the mysql.h file. I compiled and installed MySQL from source and installed it in the /usr/local/mysql/ directory, if your installation is in a different place, you might have to adjust these parameters. (An excellent guide on compiling and installing MySQL on OS X is available at http://hivelogic.com: “Installing MySQL on Mac OS X“)

When you execute the above command, you should see an output like this:

/usr/share/apr-1/build-1/libtool --silent --mode=compile gcc    -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp  -I/usr/include/apache2  -I/usr/include/apr-1   -I/usr/include/apr-1  -arch x86_64 -I/usr/local/mysql/include/mysql/ -Dlmysqlclient  -c -o mod_auth_mysql.lo mod_auth_mysql.c && touch mod_auth_mysql.slo
/usr/share/apr-1/build-1/libtool --silent --mode=link gcc -o mod_auth_mysql.la -arch x86_64  -L/usr/local/mysql/lib/ -lm -lz -rpath /usr/libexec/apache2 -module -avoid-version    mod_auth_mysql.lo
/usr/share/httpd/build/instdso.sh SH_LIBTOOL='/usr/share/apr-1/build-1/libtool' mod_auth_mysql.la /usr/libexec/apache2
/usr/share/apr-1/build-1/libtool --mode=install cp mod_auth_mysql.la /usr/libexec/apache2/
cp .libs/mod_auth_mysql.so /usr/libexec/apache2/mod_auth_mysql.so
cp .libs/mod_auth_mysql.lai /usr/libexec/apache2/mod_auth_mysql.la
cp .libs/mod_auth_mysql.a /usr/libexec/apache2/mod_auth_mysql.a
ranlib /usr/libexec/apache2/mod_auth_mysql.a
chmod 644 /usr/libexec/apache2/mod_auth_mysql.a
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/libexec/apache2

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `DYLD_LIBRARY_PATH' environment variable
     during execution

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /usr/libexec/apache2/mod_auth_mysql.so
[activating module `mysql_auth' in /private/etc/apache2/httpd.conf]

If there are no error messages, you can test the apache configuration with apachectl:

$ apachectl configtest

If the output is

Syntax OK

you can continue by restarting apache:

$ sudo apachectl graceful

The next step would be to set up your locations in http.conf, but that’s for another time…