Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
58b838d
enhacement: Search only for revision info and not entire entity
DvLogys Mar 31, 2026
d704d4a
refactor: Optimize imports
DvLogys Mar 31, 2026
be9291d
enhancement: Use cache for isLeaf calls
DvLogys Mar 31, 2026
02bda84
setup: Add time and size limit to cache
DvLogys Mar 31, 2026
8aeba73
enhancement: Set role entity loading to lazy
DvLogys Apr 1, 2026
d6828ce
refactor: Suppress warnings in copy constructor
DvLogys Apr 1, 2026
9b6c024
enhancement: Remove RU collections proxy init in service
DvLogys Apr 1, 2026
267743b
setup: Update gitignore
DvLogys Apr 1, 2026
13cc7eb
refactor: Remove unused code
DvLogys Apr 1, 2026
3e0a978
refactor: Optimize imports
DvLogys Apr 1, 2026
1eaf2a0
enhancement: Add cache to Recording unit service
DvLogys Apr 1, 2026
fbac6e8
enhancement: Add cache to Spatial unit service
DvLogys Apr 1, 2026
6993512
enhancement: Add cache to Spatial unit service
DvLogys Apr 1, 2026
4e8ef67
enhancement: Remove related entity lazy initialization
DvLogys Apr 1, 2026
b170074
enhancement: Remove related entity lazy initialization in all services
DvLogys Apr 1, 2026
e7a8d02
Replace rendered attribute with jstl tags in fieldCore
gregblt Apr 1, 2026
82a67d4
Merge branch 'enhancement/optimization' into enhancement/optimization…
gregblt Apr 1, 2026
dd37976
Replace rendered attribute with jstl tags in fieldCore
gregblt Apr 1, 2026
500882f
enhancement: Test find last revision
DvLogys Apr 1, 2026
9667743
Merge remote-tracking branch 'origin/enhancement/optimization-greg' i…
DvLogys Apr 1, 2026
d3f4ed1
refactor: Add base API exception handling
DvLogys Apr 1, 2026
1bbd312
feat: Add RestExceptionHandlerTest
DvLogys Apr 1, 2026
7e0cc07
refactor: Optimize imports
DvLogys Apr 1, 2026
c45c376
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
d106532
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
e7bf0e2
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
136c761
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
f99cb7c
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
267eb2a
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
6e9ca5c
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
7d5ad3b
test: Add tests to RecordingUnitServiceTest.java
DvLogys Apr 1, 2026
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ siamois-e2e/playwright-report/
siamois-e2e/blob-report/
siamois-e2e/playwright/.cache/
siamois-e2e/playwright/.auth/
siamois-e2e/siamois-e2e.iml
siamois-e2e/siamois-e2e.iml
siamois-e2e/.idea
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@
<scope>test</scope>
</dependency>

<!-- Source: https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.2.3</version>
<scope>compile</scope>
</dependency>

</dependencies>

Expand Down

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/main/java/fr/siamois/SiamoisApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;


@SpringBootApplication
@EnableCaching
public class SiamoisApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ public ActionUnit(@NonNull ActionUnit unit) {
)
private Set<Document> documents = new HashSet<>();

@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.actionUnit")
@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.actionUnit")
private Set<ActionUnitFormMapping> formsAvailable = new HashSet<>();

@ManyToMany(fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "action_action_code",
joinColumns = {@JoinColumn(name = "fk_action_id")},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class PendingActionUnitAttribution implements Serializable {
@JoinColumn(name = "fk_action_unit_id")
private ActionUnit actionUnit;

@ManyToOne(fetch = FetchType.EAGER)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_role_id")
private Concept role = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
import org.hibernate.envers.RevisionNumber;
import org.hibernate.envers.RevisionTimestamp;

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;

/**
* Custom revision entity to store additional information about revisions.
* Note on Revtype : 0 -> ADD, 1 -> UPDATE, 2 -> DELETE
Expand Down Expand Up @@ -49,5 +53,7 @@ public class InfoRevisionEntity {
@JoinColumn(name = "fk_institution_id", nullable = false)
protected Institution updatedFrom;


public OffsetDateTime getRevisionDate() {
return OffsetDateTime.ofInstant(Instant.ofEpochMilli(epochTimestamp), ZoneId.systemDefault());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class RecordingUnit extends RecordingUnitParent implements ArkEntity, ReferencableEntity {

@SuppressWarnings("CopyConstructorMissesField")
public RecordingUnit(RecordingUnit recordingUnit) {
setType(recordingUnit.getType());
setActionUnit(recordingUnit.getActionUnit());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@
import fr.siamois.domain.models.institution.Institution;
import fr.siamois.domain.models.vocabulary.Concept;
import fr.siamois.domain.services.ArkEntityService;
import fr.siamois.domain.services.InstitutionService;
import fr.siamois.domain.services.vocabulary.ConceptService;
import fr.siamois.dto.entity.*;
import fr.siamois.infrastructure.database.repositories.actionunit.ActionCodeRepository;
import fr.siamois.infrastructure.database.repositories.actionunit.ActionUnitRepository;
import fr.siamois.infrastructure.database.repositories.team.TeamMemberRepository;
import fr.siamois.mapper.ActionUnitMapper;
import fr.siamois.mapper.PersonMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Hibernate;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -51,8 +50,6 @@ public class ActionUnitService implements ArkEntityService {
private final ActionUnitRepository actionUnitRepository;
private final ConceptService conceptService;
private final ActionCodeRepository actionCodeRepository;
private final TeamMemberRepository teamMemberRepository;
private final InstitutionService institutionService;
private final ActionUnitMapper actionUnitMapper;
private final PersonMapper personMapper;

Expand All @@ -79,16 +76,6 @@ public Page<ActionUnitDTO> findAllByInstitutionAndByNameContainingAndByCategorie
//wireChildrenAndParents(res.getContent()); // Load and attach spatial hierarchy relationships


// load related actions
res.forEach(actionUnit -> {
Hibernate.initialize(actionUnit.getSpatialContext());
Hibernate.initialize(actionUnit.getRecordingUnitList());
Hibernate.initialize(actionUnit.getParents());
Hibernate.initialize(actionUnit.getChildren());

});


return res.map(actionUnitMapper::convert
);
}
Expand Down Expand Up @@ -117,14 +104,6 @@ public Page<ActionUnitDTO> findAllByInstitutionAndBySpatialUnitAndByNameContaini
//wireChildrenAndParents(res.getContent()); // Load and attach spatial hierarchy relationships


// load related actions
res.forEach(actionUnit -> {
Hibernate.initialize(actionUnit.getSpatialContext());
Hibernate.initialize(actionUnit.getRecordingUnitList());
Hibernate.initialize(actionUnit.getParents());
Hibernate.initialize(actionUnit.getChildren());

});


return res.map(actionUnitMapper::convert
Expand Down Expand Up @@ -257,6 +236,11 @@ public List<ActionUnit> findWithoutArk(Institution institution) {
* @return The saved ActionUnit
*/
@Override
@CacheEvict({
"InstitutionHasRootChildrenAU",
"InstitutionHasRootChildrenSU",
"ActionUnitHasChildrenInInstitution"
})
public AbstractEntityDTO save(AbstractEntityDTO toSave) {
try {
return actionUnitMapper.convert(
Expand Down Expand Up @@ -415,7 +399,6 @@ public boolean isManagerOf(ActionUnitSummaryDTO action, PersonDTO person) {
*/
public List<ActionUnitDTO> findAllWithoutParentsByInstitution(Long institutionId) {
List<ActionUnit> res = actionUnitRepository.findRootsByInstitution(institutionId);
initializeActionUnitCollections(res);
return res.stream()
.map(actionUnitMapper::convert)
.toList();
Expand All @@ -430,7 +413,6 @@ public List<ActionUnitDTO> findAllWithoutParentsByInstitution(Long institutionId
*/
public List<ActionUnitDTO> findChildrenByParentAndInstitution(Long parentId, Long institutionId) {
List<ActionUnit> res = actionUnitRepository.findChildrenByParentAndInstitution(parentId, institutionId);
initializeActionUnitCollections(res);
return res.stream()
.map(actionUnitMapper::convert)
.toList();
Expand All @@ -444,20 +426,11 @@ public List<ActionUnitDTO> findChildrenByParentAndInstitution(Long parentId, Lon
*/
public List<ActionUnitDTO> findBySpatialContext(Long spatialId) {
List<ActionUnit> res = actionUnitRepository.findBySpatialContext(spatialId);
initializeActionUnitCollections(res);
return res.stream()
.map(actionUnitMapper::convert)
.toList();
}

// Reusable method to initialize collections
private void initializeActionUnitCollections(List<ActionUnit> actionUnits) {
actionUnits.forEach(au -> {
Hibernate.initialize(au.getParents());
Hibernate.initialize(au.getChildren());
Hibernate.initialize(au.getRecordingUnitList());
});
}

public List<ActionUnitDTO> findByTeamMember(PersonDTO member, InstitutionDTO institution) {
List<ActionUnit> actionUnits = actionUnitRepository.findByTeamMemberOrCreatorAndInstitution(member.getId(), institution.getId());
Expand All @@ -474,6 +447,7 @@ public List<ActionUnitDTO> findByTeamMember(PersonDTO member, InstitutionDTO ins
* @param institutionId the institution ID
* @return True if they are children
*/
@Cacheable("ActionUnitHasChildrenInInstitution")
public boolean existsChildrenByParentAndInstitution(Long parentId, Long institutionId) {
return actionUnitRepository.existsChildrenByParentAndInstitution(parentId, institutionId);
}
Expand All @@ -485,10 +459,12 @@ public boolean existsChildrenByParentAndInstitution(Long parentId, Long institut
* @param institutionId the institution ID
* @return True if they are children
*/
@Cacheable("InstitutionHasRootChildrenAU")
public boolean existsRootChildrenByInstitution(Long institutionId) {
return actionUnitRepository.existsRootChildrenByInstitution(institutionId);
}

@Cacheable("InstitutionHasRootChildrenSU")
public boolean existsRootChildrenByRelatedSpatialUnit(Long spatialUnitId) {
return actionUnitRepository.existsRootChildrenByRelatedSpatialUnit(spatialUnitId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -116,6 +117,31 @@ public <D extends AbstractEntityDTO> RevisionWithInfo<D> findLastRevisionForEnti
}
}

/**
* Find the last revision info of the entity with the given ID.
*
* @param dtoClass The class of the entity
* @param entityId The ID of the entity
* @return The revision info
* @param <D> The type of the entity
*/
@Nullable
public <D extends AbstractEntityDTO> InfoRevisionEntity findLastRevisionInfoFor(Class<D> dtoClass, Long entityId) {
Class<?> entityClass = registry.getEntityClass(dtoClass);
if (entityClass == null) {
throw new IllegalArgumentException("No JPA Entity mapped for DTO: " + dtoClass.getName());
}
Number maxRevisionNumber = (Number) auditReader.createQuery()
.forRevisionsOfEntity(entityClass, false, true)
.add(AuditEntity.id().eq(entityId))
.addProjection(AuditEntity.revisionNumber().max())
.getSingleResult();

if (maxRevisionNumber == null) return null;

return auditReader.findRevision(InfoRevisionEntity.class, maxRevisionNumber.longValue());
}

/**
* Restores the non-audited fields of a revision entity by copying their values from the original entity.
* This method only updates the in-memory state of the revision entity and does not persist it to the database.
Expand Down
Loading
Loading