Skip to content

Commit 5335fac

Browse files
Lazy working with tests
1 parent 6b8f038 commit 5335fac

11 files changed

Lines changed: 120 additions & 34 deletions

File tree

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.eclipse.serializer.persistence.binary.jdk17.java.util.BinaryHandlerImmutableCollectionsList12;
2727
import org.eclipse.serializer.persistence.binary.jdk17.java.util.BinaryHandlerImmutableCollectionsSet12;
2828
import org.eclipse.serializer.persistence.types.Storer;
29+
import org.eclipse.serializer.reference.LazyReferenceManager;
2930
import org.eclipse.serializer.reference.ObjectSwizzling;
3031
import org.eclipse.store.storage.embedded.types.EmbeddedStorageFoundation;
3132
import org.eclipse.store.storage.types.StorageManager;
@@ -273,6 +274,7 @@ public synchronized void stop()
273274
this.registry.reset();
274275
this.entityClassToIdSetter.clear();
275276
LOG.info("Stopped storage.");
277+
LazyReferenceManager.get().stop();
276278
}
277279
else
278280
{

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazy.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import software.xdev.spring.data.eclipse.store.exceptions.LazyNotUnlinkableException;
2626
import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier;
27-
import software.xdev.spring.data.eclipse.store.repository.support.copier.copier.RegisteringObjectCopier;
27+
import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier;
2828

2929

3030
/**
@@ -40,7 +40,7 @@ static <T> SpringDataEclipseStoreLazy.Default<T> build(final T objectToWrapInLaz
4040
return new Default<>(objectToWrapInLazy);
4141
}
4242

43-
SpringDataEclipseStoreLazy<T> copyOnlyWithReference();
43+
SpringDataEclipseStoreLazy<T> copyWithReference();
4444

4545
void unlink();
4646

@@ -50,7 +50,7 @@ static <T> SpringDataEclipseStoreLazy.Default<T> build(final T objectToWrapInLaz
5050

5151
interface Internals
5252
{
53-
static <T> SpringDataEclipseStoreLazy.Default<T> build(final Lazy<T> lazySubject)
53+
static <T> SpringDataEclipseStoreLazy.Default<T> buildWithLazy(final Lazy<T> lazySubject)
5454
{
5555
return new Default<>(lazySubject);
5656
}
@@ -68,7 +68,7 @@ class Default<T> implements SpringDataEclipseStoreLazy<T>
6868
private Lazy<T> wrappedLazy;
6969
private long objectId = Swizzling.notFoundId();
7070
private transient ObjectSwizzling loader;
71-
private transient RegisteringObjectCopier copier;
71+
private transient WorkingCopier<T> copier;
7272
private transient boolean isStored = false;
7373

7474
private Default(final Lazy<T> lazySubject)
@@ -81,7 +81,7 @@ private Default(final T objectToBeWrapped)
8181
this.objectToBeWrapped = objectToBeWrapped;
8282
}
8383

84-
private Default(final long objectId, final ObjectSwizzling loader, final RegisteringObjectCopier copier)
84+
private Default(final long objectId, final ObjectSwizzling loader, final WorkingCopier<T> copier)
8585
{
8686
this.objectId = objectId;
8787
this.loader = loader;
@@ -104,8 +104,12 @@ private Lazy<T> createNewDefaultLazyWithClearableReference()
104104
Objects.requireNonNull(this.loader);
105105
Objects.requireNonNull(this.objectId);
106106
Objects.requireNonNull(this.copier);
107+
108+
final T originalInstance = (T)this.loader.getObject(this.objectId);
109+
final T copiedInstance = this.copier.onlyCreateCopy(originalInstance, false);
110+
107111
return Lazy.New(
108-
(T)this.copier.copy(this.loader.getObject(this.objectId)),
112+
copiedInstance,
109113
Swizzling.nullId(),
110114
this.loader
111115
);
@@ -211,13 +215,15 @@ public T getObjectToBeWrapped()
211215
}
212216

213217
@Override
214-
public SpringDataEclipseStoreLazy<T> copyOnlyWithReference()
218+
public SpringDataEclipseStoreLazy<T> copyWithReference()
215219
{
216-
return new SpringDataEclipseStoreLazy.Default(
220+
final SpringDataEclipseStoreLazy.Default newLazy = new SpringDataEclipseStoreLazy.Default(
217221
this.objectId(),
218222
this.loader,
219223
this.copier
220224
);
225+
newLazy.wrappedLazy = this.wrappedLazy;
226+
return newLazy;
221227
}
222228

223229
// TODO is this necessary?
@@ -235,6 +241,8 @@ public void unlink()
235241
objectIdField,
236242
wrappedDefaultLazy))
237243
{
244+
// The lazy object should be seen as "stored" by the LazyManager.
245+
// Therefore, we must set the objectId to Swizzling.nullId().
238246
fam.writeValueOfField(wrappedDefaultLazy, Swizzling.nullId(), true);
239247
}
240248
}

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/lazy/SpringDataEclipseStoreLazyBinaryHandler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import org.eclipse.serializer.reference.ObjectSwizzling;
3030
import org.eclipse.serializer.reflect.XReflect;
3131

32-
import software.xdev.spring.data.eclipse.store.repository.support.copier.copier.RegisteringObjectCopier;
32+
import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier;
3333

3434

3535
/**
@@ -61,19 +61,19 @@ public final class SpringDataEclipseStoreLazyBinaryHandler
6161
SpringDataEclipseStoreLazy.Default.class,
6262
long.class,
6363
ObjectSwizzling.class,
64-
RegisteringObjectCopier.class
64+
WorkingCopier.class
6565
)
6666
);
6767

6868
public static final int OFFSET_UNWRAPPED_OBJECT = 8;
6969
public static final int OFFSET_LAZY = 0;
7070

7171
private final ObjectSwizzling originalStoreLoader;
72-
private final RegisteringObjectCopier copier;
72+
private final WorkingCopier<?> copier;
7373

7474
public SpringDataEclipseStoreLazyBinaryHandler(
7575
final ObjectSwizzling originalStoreLoader,
76-
final RegisteringObjectCopier copier)
76+
final WorkingCopier<?> copier)
7777
{
7878
super(
7979
SpringDataEclipseStoreLazy.Default.genericType(),

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/copier/AbstractRegisteringCopier.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import software.xdev.spring.data.eclipse.store.repository.SupportedChecker;
2929
import software.xdev.spring.data.eclipse.store.repository.lazy.SpringDataEclipseStoreLazyBinaryHandler;
30+
import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier;
3031

3132

3233
/**
@@ -40,26 +41,29 @@ public abstract class AbstractRegisteringCopier implements RegisteringObjectCopi
4041
public AbstractRegisteringCopier(
4142
final SupportedChecker supportedChecker,
4243
final RegisteringWorkingCopyAndOriginal register,
43-
final ObjectSwizzling objectSwizzling)
44+
final ObjectSwizzling objectSwizzling,
45+
final WorkingCopier<?> copier)
4446
{
4547
this.actualCopier = new EclipseSerializerRegisteringCopier(
4648
supportedChecker,
4749
register,
4850
this.createPersistenceManager(
4951
this.createSerializerFoundation(),
50-
objectSwizzling
52+
objectSwizzling,
53+
copier
5154
)
5255
);
5356
}
5457

5558
private PersistenceManager<Binary> createPersistenceManager(
5659
final SerializerFoundation<?> serializerFoundation,
57-
final ObjectSwizzling objectSwizzling)
60+
final ObjectSwizzling objectSwizzling,
61+
final WorkingCopier<?> copier)
5862
{
5963
return serializerFoundation
6064
.registerCustomTypeHandler(BinaryHandlerImmutableCollectionsSet12.New())
6165
.registerCustomTypeHandler(BinaryHandlerImmutableCollectionsList12.New())
62-
.registerCustomTypeHandlers(new SpringDataEclipseStoreLazyBinaryHandler(objectSwizzling, this))
66+
.registerCustomTypeHandlers(new SpringDataEclipseStoreLazyBinaryHandler(objectSwizzling, copier))
6367
.createPersistenceManager();
6468
}
6569

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/copier/RegisteringStorageToWorkingCopyCopier.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import software.xdev.spring.data.eclipse.store.repository.SupportedChecker;
2121
import software.xdev.spring.data.eclipse.store.repository.WorkingCopyRegistry;
22+
import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier;
2223

2324

2425
/**
@@ -30,12 +31,14 @@ public class RegisteringStorageToWorkingCopyCopier extends AbstractRegisteringCo
3031
public RegisteringStorageToWorkingCopyCopier(
3132
final WorkingCopyRegistry registry,
3233
final SupportedChecker supportedChecker,
33-
final ObjectSwizzling objectSwizzling)
34+
final ObjectSwizzling objectSwizzling,
35+
final WorkingCopier<?> copier)
3436
{
3537
super(
3638
supportedChecker,
3739
(workingCopy, objectToStore) -> registry.register(workingCopy, objectToStore),
38-
objectSwizzling
40+
objectSwizzling,
41+
copier
3942
);
4043
}
4144
}

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/copier/RegisteringWorkingCopyToStorageCopier.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import software.xdev.spring.data.eclipse.store.repository.SupportedChecker;
2121
import software.xdev.spring.data.eclipse.store.repository.WorkingCopyRegistry;
22+
import software.xdev.spring.data.eclipse.store.repository.support.copier.working.WorkingCopier;
2223

2324

2425
/**
@@ -31,12 +32,14 @@ public class RegisteringWorkingCopyToStorageCopier extends AbstractRegisteringCo
3132
public RegisteringWorkingCopyToStorageCopier(
3233
final WorkingCopyRegistry registry,
3334
final SupportedChecker supportedChecker,
34-
final ObjectSwizzling objectSwizzling)
35+
final ObjectSwizzling objectSwizzling,
36+
final WorkingCopier<?> copier)
3537
{
3638
super(
3739
supportedChecker,
3840
(workingCopy, objectToStore) -> registry.invertRegister(workingCopy, objectToStore),
39-
objectSwizzling
41+
objectSwizzling,
42+
copier
4043
);
4144
}
4245
}

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/RecursiveWorkingCopier.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ public RecursiveWorkingCopier(
7070
this.domainClass = domainClass;
7171
this.registry = registry;
7272
this.workingCopyToStorageCopier =
73-
new RegisteringWorkingCopyToStorageCopier(registry, supportedChecker, objectSwizzling);
73+
new RegisteringWorkingCopyToStorageCopier(registry, supportedChecker, objectSwizzling, this);
7474
this.storageToWorkingCopyCopier =
75-
new RegisteringStorageToWorkingCopyCopier(registry, supportedChecker, objectSwizzling);
75+
new RegisteringStorageToWorkingCopyCopier(registry, supportedChecker, objectSwizzling, this);
7676
this.idSetterProvider = idSetterProvider;
7777
this.persistableChecker = persistableChecker;
7878
}
@@ -182,12 +182,14 @@ private <E> void mergeValues(
182182
{
183183
alreadyMergedTargets.collectMergedTarget(targetObject);
184184

185-
if(sourceObject instanceof String)
185+
if(sourceObject instanceof String || sourceObject instanceof SpringDataEclipseStoreLazy<?>)
186186
{
187187
// no merge needed and no merge possible
188188
return;
189189
}
190-
AccessHelper.getInheritedPrivateFieldsByName(sourceObject.getClass()).values().forEach(
190+
final Collection<Field> valuesToMerge =
191+
AccessHelper.getInheritedPrivateFieldsByName(sourceObject.getClass()).values();
192+
valuesToMerge.forEach(
191193
field ->
192194
this.mergeValueOfField(
193195
sourceObject,
@@ -333,11 +335,17 @@ private <E> SpringDataEclipseStoreLazy<E> createNewLazy(
333335
}
334336
else
335337
{
336-
final Lazy<E> newLazyForBuilding = Lazy.Reference(oldLazy.get());
338+
// This object is already stored but the new version must get overwritten.
339+
// The oldLazy Object can contain all kinds of objects (including more lazies)
340+
final E copyOfWrappedObject = this.getOrCreateObjectForDatastore(
341+
oldLazy.get(),
342+
true,
343+
alreadyMergedTargets,
344+
changedCollector);
337345
oldLazy.unlink();
338346
newLazy.unlink();
339-
// This object is already stored but the new version must get overwritten.
340-
return SpringDataEclipseStoreLazy.Internals.build(newLazyForBuilding);
347+
348+
return SpringDataEclipseStoreLazy.Internals.buildWithLazy(Lazy.Reference(copyOfWrappedObject));
341349
}
342350
}
343351
final E copyOfWrappedObject = this.getOrCreateObjectForDatastore(
@@ -354,7 +362,7 @@ private <E> SpringDataEclipseStoreLazy<E> createNewLazy(
354362
oldLazy.unlink();
355363
// This lazy should never be used again!
356364
// It is though of as a temporary copy to merge back into the original-storage-data.
357-
return (SpringDataEclipseStoreLazy<E>)newLazy.copyOnlyWithReference();
365+
return (SpringDataEclipseStoreLazy<E>)newLazy.copyWithReference();
358366
}
359367
}
360368

@@ -396,7 +404,8 @@ private <E> E[] createGenericObjectArray(
396404
return newArray;
397405
}
398406

399-
private <E> E onlyCreateCopy(final E objectToCopy, final boolean invertRegistry)
407+
@Override
408+
public <E> E onlyCreateCopy(final E objectToCopy, final boolean invertRegistry)
400409
{
401410
if(invertRegistry)
402411
{

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/working/WorkingCopier.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public interface WorkingCopier<T>
5050
*/
5151
WorkingCopierResult<T> mergeBack(T workingCopy);
5252

53+
<E> E onlyCreateCopy(final E objectToCopy, final boolean invertRegistry);
54+
5355
/**
5456
* @return the original entity that corresponds to the given working copy object.
5557
*/

spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/helper/DummyWorkingCopier.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ public WorkingCopierResult<T> mergeBack(final T workingCopy)
4141
return null;
4242
}
4343

44+
@Override
45+
public <E> E onlyCreateCopy(final E objectToCopy, final boolean invertRegistry)
46+
{
47+
return objectToCopy;
48+
}
49+
4450
@Override
4551
public T getOriginal(final T workingCopy)
4652
{

spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/lazy/LazyTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,50 @@ void lazyChangeComplexObject(@Autowired final ObjectWithLazyRepository<ComplexLa
268268
);
269269
}
270270

271+
@Test
272+
void lazyReloadAndRestoreComplexObject(@Autowired final ObjectWithLazyRepository<ComplexLazyObject> repository)
273+
{
274+
final ObjectWithLazy<ComplexLazyObject> newLazy = new ObjectWithLazy<>();
275+
final ComplexLazyObject objectToStore = new ComplexLazyObject(
276+
SpringDataEclipseStoreLazy.build(new SimpleObject(TestData.DUMMY_STRING)),
277+
new ArrayList<>(Arrays.asList(
278+
SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING))),
279+
SpringDataEclipseStoreLazy.build(new ArrayList<>(Arrays.asList(TestData.DUMMY_STRING_ALTERNATIVE)))
280+
))
281+
);
282+
newLazy.setLazy(SpringDataEclipseStoreLazy.build(objectToStore));
283+
repository.save(newLazy);
284+
285+
restartDatastore(this.configuration);
286+
287+
final ObjectWithLazy<ComplexLazyObject> loadedObjectToChange = repository.findAll().get(0);
288+
repository.save(loadedObjectToChange);
289+
290+
TestUtil.doBeforeAndAfterRestartOfDatastore(
291+
this.configuration,
292+
() -> {
293+
final ObjectWithLazy<ComplexLazyObject> loadedObject = repository.findAll().get(0);
294+
Assertions.assertNotSame(loadedObjectToChange, loadedObject);
295+
Assertions.assertNotSame(
296+
loadedObjectToChange.getLazy().get(),
297+
loadedObject.getLazy().get()
298+
);
299+
Assertions.assertEquals(
300+
loadedObjectToChange.getLazy().get().getListOfLazyListOfString().size(),
301+
loadedObject.getLazy().get().getListOfLazyListOfString().size()
302+
);
303+
Assertions.assertEquals(
304+
loadedObjectToChange.getLazy().get().getListOfLazyListOfString().get(0).get().size(),
305+
loadedObject.getLazy().get().getListOfLazyListOfString().get(0).get().size()
306+
);
307+
Assertions.assertEquals(
308+
loadedObjectToChange.getLazy().get().getListOfLazyListOfString().get(0).get().get(0),
309+
loadedObject.getLazy().get().getListOfLazyListOfString().get(0).get().get(0)
310+
);
311+
}
312+
);
313+
}
314+
271315
@Test
272316
void lazyClearBeforeSave()
273317
{

0 commit comments

Comments
 (0)