Skip to content

Commit

Permalink
Allow subclasses of DefaultBindableModel to be serialized (#20)
Browse files Browse the repository at this point in the history
* Allow subclasses of DefaultBindableModel to be serialized

+ Bumps gradle version to 4.1
+ Fixes up gitignore
+ Adds a test that uses FST serialization

* remove volatile
  • Loading branch information
safreiberg authored and dcervelli committed Dec 4, 2017
1 parent 97f34f6 commit 358b773
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 3 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@ target/
.*.swp
*~
.settings
build/
build/
out/
.classpath
.project
*.iml
*.ipr
*.iws
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.5'
runtime group: 'org.slf4j', name: 'slf4j-simple', version:'1.7.5'
testCompile group: 'junit', name: 'junit', version:'4.11'
testCompile group: 'de.ruedigermoeller', name: 'fst', version: '2.55'
}

task sourceJar(type: Jar) {
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
distributionUrl=https://services.gradle.org/distributions/gradle-4.1-bin.zip
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// limitations under the License.
package com.palantir.ptoss.cinch.core;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

Expand All @@ -21,7 +23,13 @@
*/
public class DefaultBindableModel implements BindableModel {

private final List<Binding> bindings = new CopyOnWriteArrayList<Binding>();
// must be transient because Bindings aren't serializable, and
// subclasses might be serialized.
private transient List<Binding> bindings;

public DefaultBindableModel() {
bindings = new CopyOnWriteArrayList<Binding>();
}

/**
* {@inheritDoc}
Expand Down Expand Up @@ -62,4 +70,9 @@ public void update() {
this.modelUpdated(ModelUpdates.UNSPECIFIED);
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
bindings = new CopyOnWriteArrayList<Binding>();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.palantir.ptoss.cinch;

import com.palantir.ptoss.cinch.core.DefaultBindableModel;

import java.io.Serializable;

public class SerializableBindableModel extends DefaultBindableModel implements Serializable {

private final String data;

public SerializableBindableModel(String data) {
super();
this.data = data;
}

public String getData() {
return data;
}

@Override
public String toString() {
return "SerializableBindableModel{" +
"data='" + data + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

SerializableBindableModel that = (SerializableBindableModel) o;

return data != null ? data.equals(that.data) : that.data == null;
}

@Override
public int hashCode() {
return data != null ? data.hashCode() : 0;
}

}
68 changes: 68 additions & 0 deletions src/test/java/com/palantir/ptoss/cinch/SerializableModelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.palantir.ptoss.cinch;

import com.palantir.ptoss.cinch.core.Binding;
import com.palantir.ptoss.cinch.core.ModelUpdate;
import org.apache.commons.lang.SerializationUtils;
import org.junit.Assert;
import org.junit.Test;
import org.nustaq.serialization.FSTConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SerializableModelTest {

private static final Logger log = LoggerFactory.getLogger(SerializableModelTest.class);
private static FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();

private final Binding testBinding = new Binding() {
@Override
public <T extends Enum<?> & ModelUpdate> void update(T... changed) {
log.info("Ran update");
}
};

@Test
public void testJavaSerialize() {
SerializableBindableModel model = new SerializableBindableModel("testing");
javaRoundTrip(model);
}

@Test
public void testJavaSerializeWithBinding() {
SerializableBindableModel model = new SerializableBindableModel("testing");
model.bind(testBinding);
model.update();
SerializableBindableModel rehydrated = javaRoundTrip(model);
rehydrated.bind(testBinding);
rehydrated.update();
}

private SerializableBindableModel javaRoundTrip(SerializableBindableModel model) {
SerializableBindableModel rehydrated = (SerializableBindableModel) SerializationUtils.clone(model);
Assert.assertEquals(model, rehydrated);
return rehydrated;
}

@Test
public void testFstSerialize() {
SerializableBindableModel model = new SerializableBindableModel("testing");
fstRoundTrip(model);
}

@Test
public void testFstSerializeWithBinding() {
SerializableBindableModel model = new SerializableBindableModel("testing");
model.bind(testBinding);
model.update();
SerializableBindableModel rehydrated = fstRoundTrip(model);
rehydrated.bind(testBinding);
rehydrated.update();
}

private SerializableBindableModel fstRoundTrip(SerializableBindableModel model) {
byte[] bytes = conf.asByteArray(model);
SerializableBindableModel rehydrated = (SerializableBindableModel)conf.asObject(bytes);
Assert.assertEquals(model, rehydrated);
return rehydrated;
}
}

0 comments on commit 358b773

Please sign in to comment.