Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@simonbasle
Last active April 28, 2016 12:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonbasle/592b86641bffb2c95943a46c3da57dfa to your computer and use it in GitHub Desktop.
Save simonbasle/592b86641bffb2c95943a46c3da57dfa to your computer and use it in GitHub Desktop.
/*
* Copyright (C) 2015 Couchbase Inc., the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.couchbase.client.spring.cache;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.document.SerializableDocument;
import com.couchbase.client.spring.cache.serialization.model.Foo;
import com.couchbase.client.spring.cache.serialization.model.Other;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import rx.Observable;
import rx.functions.Func1;
import static com.couchbase.client.spring.cache.serialization.model.SharedCache.SharedCache;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class DeepSerializationTest {
private final String cacheName = "test";
private int DEEP_LEVEL = 4;
@Autowired
private Bucket client;
private CouchbaseCache cache;
@Before
public void setUp() {
cache = new CouchbaseCache(cacheName, client);
SharedCache.setCache(cache);
}
@Test
public void testJavaSerialization() throws IOException, ClassNotFoundException {
Foo f = getFooStructure();
FileOutputStream fos = new FileOutputStream("temp.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(f);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("temp.out");
ObjectInputStream oin = new ObjectInputStream(fis);
Foo storedFoo = (Foo) oin.readObject();
System.out.println(storedFoo);
}
/**
* The following test will fail to deserialize when DEEP_LEVEL is larger than number of thread pool
*/
@Test
public void shouldDeserializeComplexObject() throws InterruptedException {
// Given
final Foo expected = getFooStructure();
// When
final Foo retrieved = getFoo(expected.getId()).toBlocking().singleOrDefault(null);
// Then
assertThat(retrieved, is(expected));
}
static final Func1<SerializableDocument, Foo> SERIAL_TO_FOO = new Func1<SerializableDocument, Foo>() {
@Override
public Foo call(SerializableDocument sd) {
return (Foo) sd.content();
}
};
static final Func1<SerializableDocument, Other> SERIAL_TO_OTHER = new Func1<SerializableDocument, Other>() {
@Override
public Other call(SerializableDocument sd) {
return (Other) sd.content();
}
};
private Observable<Foo> getFoo(String fooId) {
return client.async()
.get(cache.getDocumentId(fooId), SerializableDocument.class)
.map(SERIAL_TO_FOO)
.flatMap(new Func1<Foo, Observable<Foo>>() {
@Override
public Observable<Foo> call(final Foo foo) {
if (foo.getOtherId() != null && foo.getOther() == null) {
return getOther(foo.getOtherId()).map(new Func1<Other, Foo>() {
@Override
public Foo call(Other other) {
foo.setOther(other);
return foo;
}
});
}
return Observable.just(foo);
}
});
}
private Observable<Other> getOther(String otherId) {
return client.async()
.get(cache.getDocumentId(otherId), SerializableDocument.class)
.map(SERIAL_TO_OTHER)
.flatMap(new Func1<Other, Observable<Other>>() {
@Override
public Observable<Other> call(final Other other) {
if (other.getFooId() != null && other.getFoo() == null) {
return getFoo(other.getFooId()).map(new Func1<Foo, Other>() {
@Override
public Other call(Foo foo) {
other.setFoo(foo);
return other;
}
});
}
return Observable.just(other);
}
});
}
/**
* Build Foo->Other object composition based on DEEP_LEVEL. For a level 3 you should see:
* Level 0 Level 1 Level 2 Level 3
* ----^---- ----^---- ----^---- ----^----
* Foo->Other
* |-> Foo->Other
* |-> Foo->Other
* |-> Foo->Other
*/
private Foo getFooStructure() {
final Foo root = createFoo(0);
Foo current = root;
for (int id = 1; id <= DEEP_LEVEL; id++) {
current.getOther().setFoo(createFoo(id));
cache.put(current.getOther().getId(), current.getOther());
current = current.getOther().getFoo();
}
// cache.put(root.getId(), root);
return root;
}
private Foo createFoo(final int id) {
final Other other = new Other();
other.setId("Other" + id);
other.setDescription("Other" + id + " description");
cache.put(other.getId(), other);
final Foo foo = new Foo();
foo.setId("Foo" + id);
foo.setDescription("Foo" + id + " description");
foo.setOther(other);
cache.put(foo.getId(), foo);
return foo;
}
}
package com.couchbase.client.spring.cache.serialization.model;
import java.io.Serializable;
public class Foo implements Serializable {
private String id;
private String description;
private String otherId;
private transient Other other;
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public String getOtherId() {
return otherId;
}
public void setOtherId(final String otherId) {
this.otherId = otherId;
}
public Other getOther() {
return other;
}
public void setOther(final Other other) {
this.otherId = other.getId();
this.other = other;
}
@Override
public String toString() {
return "Foo{" +
"id='" + id + '\'' +
", description='" + description + '\'' +
", otherId='" + otherId + '\'' +
", other=" + other +
'}';
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Foo foo = (Foo) o;
if (id != null ? !id.equals(foo.id) : foo.id != null) return false;
if (description != null ? !description.equals(foo.description) : foo.description != null) return false;
if (otherId != null ? !otherId.equals(foo.otherId) : foo.otherId != null) return false;
return other != null ? other.equals(foo.other) : foo.other == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (otherId != null ? otherId.hashCode() : 0);
result = 31 * result + (other != null ? other.hashCode() : 0);
return result;
}
}
package com.couchbase.client.spring.cache.serialization.model;
import java.io.Serializable;
public class Other implements Serializable {
private String id;
private String description;
private String fooId;
private transient Foo foo;
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public String getFooId() {
return fooId;
}
public void setFooId(final String fooId) {
this.fooId = fooId;
}
public Foo getFoo() {
return foo;
}
public void setFoo(final Foo foo) {
this.fooId = foo.getId();
this.foo = foo;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Other other = (Other) o;
if (id != null ? !id.equals(other.id) : other.id != null) return false;
if (description != null ? !description.equals(other.description) : other.description != null) return false;
if (fooId != null ? !fooId.equals(other.fooId) : other.fooId != null) return false;
return foo != null ? foo.equals(other.foo) : other.foo == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (fooId != null ? fooId.hashCode() : 0);
result = 31 * result + (foo != null ? foo.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "Other{" +
"id='" + id + '\'' +
", description='" + description + '\'' +
", fooId='" + fooId + '\'' +
", foo=" + foo +
'}';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment