Skip to content

v2.3.1 #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# 2.3.1

* Auto-Fix problems with adding ids to entities with existing data store.

# 2.3.0

* Add support for shuting down the storage during application shutdown
* By default only enabled when Spring DevTools are active
* Add support for shutting down the storage during application shutdown
* By default, only enabled when Spring DevTools are active
* This should fix "StorageExceptionInitialization: Active storage for ... already exists" errors during DevTools restart
* Added [Jakarta Bean Validation Constraints](https://jakarta.ee/learn/docs/jakartaee-tutorial/current/beanvalidation/bean-validation/bean-validation.html#_using_jakarta_bean_validation_constraints) with Hibernate validator for entities.

Expand Down
6 changes: 3 additions & 3 deletions docs/antora.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: ROOT
title: Spring-Data-Eclipse-Store
version: master
display_version: '2.3.0'
display_version: '2.3.1'
start_page: index.adoc
nav:
- modules/ROOT/nav.adoc
asciidoc:
attributes:
product-name: 'Spring-Data-Eclipse-Store'
display-version: '2.3.0'
maven-version: '2.3.0'
display-version: '2.3.1'
maven-version: '2.3.1'
page-editable: false
page-out-of-support: false
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,14 @@ private <T, ID> void setIdManagerForEntityData(final Class<T> entityClass, final
{
final IdManager<T, ID> idManager = this.ensureIdManager(entityClass);
final EntityData<T, Object> entityData = root.getCurrentRootData().getEntityData(entityClass);
entityData.setIdGetter(idManager::getId);
if(idManager.hasIdField())
{
entityData.setIdGetter(idManager::getId);
}
else
{
entityData.setIdGetter(null);
}
}

public synchronized <T> void registerEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,27 @@ public EntityData()
this.entitiesById = new HashMap<>();
}

/**
* Accepts {@code null} if no id field is defined
*/
public void setIdGetter(final Function<T, ID> idGetter)
{
this.idGetter = idGetter;

this.ensureEntitiesAndEntitiesByIdAreTheSameSize();
}

private void ensureEntitiesAndEntitiesByIdAreTheSameSize()
{
if(this.idGetter != null && this.entities.size() != this.entitiesById.size())
{
this.entitiesById.clear();
this.entities.forEach(entity -> this.entitiesById.put(this.idGetter.apply(entity), entity));
}
if(this.idGetter == null)
{
this.entitiesById.clear();
}
}

public IdentitySet<T> getEntities()
Expand Down Expand Up @@ -83,7 +101,10 @@ public Collection<Object> ensureEntityAndReturnObjectsToStore(final T entityToSt
if(!this.getEntities().contains(entityToStore))
{
this.entities.add(entityToStore);
this.entitiesById.put(this.idGetter.apply(entityToStore), entityToStore);
if(this.idGetter != null)
{
this.entitiesById.put(this.idGetter.apply(entityToStore), entityToStore);
}
return this.getObjectsToStore();
}
return List.of();
Expand All @@ -97,7 +118,10 @@ public Collection<Object> getObjectsToStore()
public Collection<Object> removeEntityAndReturnObjectsToStore(final T entityToRemove)
{
this.entities.remove(entityToRemove);
this.entitiesById.remove(this.idGetter.apply(entityToRemove));
if(this.idGetter != null)
{
this.entitiesById.remove(this.idGetter.apply(entityToRemove));
}
return this.getObjectsToStore();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,33 @@ void replaceWithId(@Autowired final CustomerWithIdIntegerNoAutoGenerateRepositor
);
}

@Test
void replaceWithIdAfterRestart(@Autowired final CustomerWithIdIntegerNoAutoGenerateRepository customerRepository)
{
final CustomerWithIdIntegerNoAutoGenerate existingCustomer =
new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME, TestData.LAST_NAME);
customerRepository.save(existingCustomer);

restartDatastore(this.configuration);

final CustomerWithIdIntegerNoAutoGenerate newCustomer =
new CustomerWithIdIntegerNoAutoGenerate(1, TestData.FIRST_NAME_ALTERNATIVE,
TestData.LAST_NAME_ALTERNATIVE);
customerRepository.save(newCustomer);

TestUtil.doBeforeAndAfterRestartOfDatastore(
this.configuration,
() -> {
final List<CustomerWithIdIntegerNoAutoGenerate> loadedCustomer =
TestUtil.iterableToList(customerRepository.findAll());

Assertions.assertEquals(1, loadedCustomer.size());
Assertions.assertEquals(TestData.FIRST_NAME_ALTERNATIVE, loadedCustomer.get(0).getFirstName());
Assertions.assertEquals(TestData.LAST_NAME_ALTERNATIVE, loadedCustomer.get(0).getLastName());
}
);
}

@Test
void replaceWithAutoId(@Autowired final CustomerWithIdIntegerRepository customerRepository)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright © 2024 XDEV Software (https://xdev.software)
*
* 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 software.xdev.spring.data.eclipse.store.repository.root;

import java.util.function.Function;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import software.xdev.spring.data.eclipse.store.helper.TestData;


class EntityDataTest
{
record Person(String id, String name)
{
}


private final Function<Person, String> idGetter = person -> person.id;
private final Function<Person, String> idNullGetter = person -> null;

@Test
void idGetterIsNotSet()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
Assertions.assertTrue(testData.getEntitiesById().isEmpty());
Assertions.assertEquals(1, testData.getEntities().size());
}

@Test
void idGetterSetAndNothingAdded()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idGetter);
Assertions.assertTrue(testData.getEntitiesById().isEmpty());
Assertions.assertTrue(testData.getEntities().isEmpty());
}

@Test
void idGetterNotSetSetAndNothingAdded()
{
final EntityData<Person, String> testData = new EntityData<>();
Assertions.assertTrue(testData.getEntitiesById().isEmpty());
Assertions.assertTrue(testData.getEntities().isEmpty());
}

@Test
void idGetterSet()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
Assertions.assertEquals(1, testData.getEntitiesById().size());
Assertions.assertEquals(1, testData.getEntities().size());
}

@Test
void idGetterSetToNull()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idNullGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
Assertions.assertEquals(1, testData.getEntitiesById().size());
Assertions.assertEquals(1, testData.getEntities().size());
}

@Test
void idGetterSetToNullWith2Entities()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idNullGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertEquals(1, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());
}

@Test
void idGetterSetWith2Entities()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertEquals(2, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());
}

@Test
void idGetterFirstNullThenReturningIdSameObject()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(null);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertTrue(testData.getEntitiesById().isEmpty());
Assertions.assertEquals(2, testData.getEntities().size());

testData.setIdGetter(this.idGetter);
final Person foundPerson = testData.getEntities().stream().findFirst().get();
testData.ensureEntityAndReturnObjectsToStore(foundPerson);
Assertions.assertEquals(2, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());
}

@Test
void idGetterFirstReturnNullThenReturningIdSameObject()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idNullGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertEquals(1, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());

testData.setIdGetter(this.idGetter);
final Person foundPerson = testData.getEntities().stream().findFirst().get();
testData.ensureEntityAndReturnObjectsToStore(foundPerson);
Assertions.assertEquals(2, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());
}

@Test
void idGetterFirstNullThenReturningIdDifferentObject()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(null);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertTrue(testData.getEntitiesById().isEmpty());
Assertions.assertEquals(2, testData.getEntities().size());

testData.setIdGetter(this.idGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
Assertions.assertEquals(2, testData.getEntitiesById().size());
Assertions.assertEquals(3, testData.getEntities().size());
}

@Test
void idGetterFirstReturnNullThenReturningIdDifferentObject()
{
final EntityData<Person, String> testData = new EntityData<>();
testData.setIdGetter(this.idNullGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
testData.ensureEntityAndReturnObjectsToStore(new Person("2", TestData.FIRST_NAME_ALTERNATIVE));
Assertions.assertEquals(1, testData.getEntitiesById().size());
Assertions.assertEquals(2, testData.getEntities().size());

testData.setIdGetter(this.idGetter);
testData.ensureEntityAndReturnObjectsToStore(new Person("1", TestData.FIRST_NAME));
Assertions.assertEquals(2, testData.getEntitiesById().size());
Assertions.assertEquals(3, testData.getEntities().size());
}
}