views:

357

answers:

2

I'm currently thinking about some design details of remoting / serialization between a Java Swing WebStart Application (Fat Client) and some remote services running on Tomcat. I want to use a http compatible transport to communicate with the server and since I'm already using Spring, I assume Spring's HTTP Remoting is a good choice. But I'm open to other alternatives here. My design problem is best illustrated with some small example

The client will call some services on the remote side. A sample service interface:

public interface ServiceInterface extends Serialiazable {
    // Get immutable reference data
    public List<Building> getBuildings();
    public List<Office> getOffices();

    // Create, read and update Employee objects
    public insertEmployee(Employee employee);
    public Employee getEmployee();
    public void updateEmployee(Employee employee);
}

Building and Office are immutable reference data objects, e.g.

public Building implements Serializable {
    String name;
    public Building(String name) { this.name = name; }
    public String getName() { return name; }
}

public Office implements Serializable {
    Building building;
    int maxEmployees;
    public Office(Building building, int maxEmployess) {
        this.building = building;
        this.maxEmployees = maxEmployees;
    }
    public Building getBuilding() { return building; }
    punlic int getMaxEmployees() { retrun maxEmployees; }
}

The available Buildings and Offices won't change during runtime and should be prefeteched by the client to have the available for selection list, filter condition, ... I want to have only one instance of each particular Building and Office on client and one instance onserver side. On server side it is not a big problem, but in my eyes the problem starts here when I call getOffices() after getBuildings(). The Buildings returned by getOffices() share the same instance of Buildings (if they have the same Building assigned) but the Buildings returned by getOffices() (referenced in Office objects) are not the same instance as the Buildings returned by getBuildings().

This might been solved by using some getReferenceDate() method returning both information in the same call, but than the problem will start if I have Employees referencing Offices.

I was thinking about some custom serialization (readObject, writeObject) transfering only the primary key and than getting the instance of the object from some class holding the reference data objects. But is this the best solution to this problem? I assume that this problem is not an uncommon problem, but did not find anything on Google. Is there a better solution? If not, what would be the best way to implemet it?

A: 

Firstly, I'd recommend using RMI for your remoting, which can be proxied over HTTP (IIRC). Secondly, if you serialize the ServiceInterface, I believe the serialization mechanism will maintain the relative references for when it is deserialized in the remote JVM.

David Grant
+1  A: 

If you're going to serialize, You'll probably need to implement readResolve to guarantee that you're not creating additional instances:

From the javadoc for Serializable:

Classes that need to designate a replacement when an instance of it is read from the stream should implement this special method with the exact signature.

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

I seem to remember reading about this approach in pre-enum days for handling serialization of objects that had to be guaranteed to be singular, like typesafe enums.

I'd also strongly recommend that you include a manual serialVersionUID in your serialized classes so that you can manually control when the application will decide that your classes represent incompatible versions that can't be deserialized.

However, on a more basic level, I'd question the whole approach - rather than trying to guarantee object identity over the network, which sounds to be, at the very least, a concurrency nightmare, why not just pass the raw data around and have your logic determine identity by id, the way we did it in my grandpappy's day? Your back end has a building object, it gets one from the front end, compares via ID (If you've altered the object on the front end you'll have to commit your object to your central datastore and determine what's changed, which could be a synchronizing issue with multiple clients, but you'd have that issue anyway).

Passing data remotely via Spring-httpclient is nice and simple, a bit less low-level than RMI.

Steve B.