Monday 2 November 2009

GXT BaseModelData not Serializable Workaround

I have been using the open source version of Ext GWT/GXT a great Widget library for GWT for some time now. As the product starts to mature the open source releases are starting to lag the paid for subscription releases as the guys at Ext JS start to try and generate some revenue out of the product they have developed, which is fair enough, I guess.

The latest open source version at the time of writing is 2.0.1.

However in my latest project I needed to be able to Java serialize some of my GXT data using Java serialization. The main data type in the GXT world is the BaseModelData which is a default implementation of the ModelData interface. BaseModelData is marked as java.io.Serializable unfortunately the implementation is not serializable in reality as it contains an RCPMap object which is not java.io.Serializable.

This issue has been raised with the guys at Ext JS, and apparently has been fixed in a release post 2.0.1, but as there is no open source release it is not available for me to use at the moment.

I looked at the possibility of patching up the source, but its not a trivial fix and due to the limitations of GWT security white list you can not override standard Serialization or Externalization to work around the issue.

So I have taken a different approach for the time being and have introduced my own implemenation of the ModelData interface which allows me to use the GXT widgets whilst at the same time being able to serialize them on the server side.

The implemenation is


import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class View /*extends BaseModelData*/ implements ViewI {

   
@Override
   
public boolean equals(Object obj) {
       
if (obj == null) return false;
       
return getKey().equals(((View)obj).getKey());
   
}


   
private static final long serialVersionUID = -1847195052298237356L;

   
private Map<String,Serializable> properties;
   
private String type;
   
private String keyProperty;

   
public View() {
    }
   
   
   
public View(String type, String keyProperty) {
       
super();
       
this.type = type;
       
this.keyProperty = keyProperty;
   
}


   
public String getKeyProperty() {
       
return keyProperty;
   
}

   
public void setKeyProperty(String keyProperty) {
       
this.keyProperty = keyProperty;
   
}

   
public void setType(String type) {
       
this.type = type;
   
}


   
@Override
   
public Serializable getKey() {
       
return get(keyProperty);
   
}

   
@Override
   
public String getKeyField() {
       
return keyProperty;
   
}

   
@Override
   
public String getType() {
       
return type;
   
}

   
@Override
   
public void setKey(Serializable key) {
       
set(keyProperty, key);
   
}


   
@Override
   
public <X> X get(String property) {
       
if (properties != null) return (X)properties.get(property);
       
return null;
   
}


   
@Override
   
public Map<String, Object> getProperties() {
       
if (properties == null) properties = new HashMap<String, Serializable>();
        Map<String,Object> returning =
new HashMap<String, Object>();
       
for (Map.Entry<String, Serializable> entry : properties.entrySet()) {
           
returning.put(entry.getKey(), entry.getValue());
       
}
       
return returning;
   
}


   
@Override
   
public Collection<String> getPropertyNames() {
       
return properties.keySet();
   
}


   
@Override
   
public <X> X remove(String property) {
       
if (properties == null) properties = new HashMap<String, Serializable>();
       
return (X)properties.remove(property);
   
}


   
@Override
   
public <X> X set(String property, X value) {
       
if (properties == null) properties = new HashMap<String, Serializable>();
       
return (X)properties.put(property, (Serializable)value);
   
}

}



where ViewI is a simple extension of the ModelData interface to add some other bits and pieces I needed.



import java.io.Serializable;

import com.extjs.gxt.ui.client.data.ModelData;

public interface ViewI extends ModelData, Serializable {
   
String getType();
    Serializable getKey
();
   
void setKey(Serializable key);
    String getKeyField
();
}



Hopefully it wont be too long before GXT releases an open source version with a workaround for this issue, but in the mean time feel free to use this code/simple approach to work around the issue.

No comments:

Post a Comment