Best of 2003

Posted 995 days ago

Thanks to the Web Archive, I was able to retrieve a bunch of old posts that I had lost a couple years ago when the server I hosted on at the time crashed. I restored the posts that had interesting content with their original publish dates, and thought I'd post a "Best of '03" to those stories. So here they are, in chronological order:

Passing J2SE Collections in EJB Remote Methods

Posted 1714 days ago

The J2SE Collection interfaces and abstract classes do not implement the Serializable interface, making it difficult to pass Collections around using EJB Remote Interfaces.

The trick to this one is to be explicit about the type of Collection you want to use. I discovered this problem while implementing the Value List Hander pattern from Sun's J2EE Patterns Catalog. If you're unfamiliar with the pattern, it allows you to iterate over a list of remote entities in an efficient manner, by utilizing the Transfer Object pattern, also from the J2EE Patterns Catalog.

I wrote an Enterprise Java Bean to act as a facade to my VLH objects in the business tier, and found that it was throwing a NotSerializableException when I attempted to return a sublist of a java.util.List reference. The List variable referenced an instance of an ArrayList object, which does implement Serializable, but since I was referencing it as a java.util.List, which does not implement Serializable, the resulting sublist was not Serializable either.

I simply changed the VLH classes to contain a reference to an ArrayList internally instead of a List. This seems to have fixed that problem, hope it helps you with yours!

Serializing Static Instances over EJB Calls

Posted 1714 days ago

I've recently run across a problem serializing "enumeration" classes over RMI method calls... here's how I resolved it.

First note that "enumeration" is in quotes for a reason, I'm not talking about the java.util.Enumeration interface. Lets say that I wanted to represent user-states in an enum, I've come to use the following pattern to accomplish this in Java in place of C/C++'s enum type:

public class UserState
{
    public final static ONLINE = new UserState( "ONLINE" );
    public final static OFFLINE = new UserState( OFFLINE );
    public final static IDLE = new UserState( "IDLE" );
    public final static AWAY = new UserState( "AWAY" );
 
    private String name;

    private UserState( String name ) {
        this.name = name;
    }
}

This provides me with four final static instances of a UserState in the system. I can compare them using the == operators, because UserState references will point to one of these four.

In the J2EE world, this works great within each tier; however as soon as you try to pass an object like this into another tier using a remote EJB method call, problems arise. When you pass an object over an EJB method call, the object is serialized on the caller's side, and deserialized on the receiver's side. When that object is deserialized, however, it has the same logical values, but is itself a NEW INSTANCE of the UserState class. This will fail any comparison made using the == operator to one of the original four static instances.

To get around this, what you need to do on the receiving side is check the logical value of the object passed in, and set that reference to be one of the original four static instances. To help facilitate this, I've added toString() and getInstance( String str ) methods to my enumeration class pattern:

public class UserState
{
    ...

    public String toString() { return name; }

    public UserState getInstance( String str )
    {
        if ( str.equals( "ONLINE" ) ) return ONLINE;
        if ( str.equals( "OFFLINE" ) ) return OFFLINE;
        if ( str.equals( "AWAY" ) ) return AWAY;
        if ( str.equals( "IDLE" ) ) return IDLE;

        return null;
    }
}

So say I had a method in an EJB's Remote interface that looked like this:

public UserState getUsersState( String username ) throws RemoteException;

On the client side, what I would need to do is this:

UserState state = ejbremotereference.getUsersState( "timfanelli" );
state = UserState.getInstance( state.toString() );

This will get the user's state from the EJB instance, and then the second line reassigns the UserState reference to point to the appropriate static instance on the client. The same type of trick would be used in the Business Tier if I were to ever pass a UserState object into the EJB.

About

My name is Tim Fanelli, I am a software engineer in Northern NY. I spend most of my time working, and when I can, I try to post interesting things here.

Cigar Dossiers