import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.hibernate.StaleStateException;
import org.onap.cps.api.exceptions.AlreadyDefinedException;
import org.onap.cps.api.exceptions.ConcurrencyException;
import org.onap.cps.api.exceptions.CpsAdminException;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
@Service
try {
fragmentRepository.saveAll(fragmentEntities);
- } catch (final StaleStateException staleStateException) {
+ } catch (final ObjectOptimisticLockingFailureException objectOptimisticLockingFailureException) {
retryUpdateDataNodesIndividually(anchorEntity, fragmentEntities);
}
}
try {
fragmentRepository.saveAll(existingFragmentEntities);
- } catch (final StaleStateException staleStateException) {
+ } catch (final ObjectOptimisticLockingFailureException objectOptimisticLockingFailureException) {
retryUpdateDataNodesIndividually(anchorEntity, existingFragmentEntities);
}
}
for (final FragmentEntity dataNodeFragment : fragmentEntities) {
try {
fragmentRepository.save(dataNodeFragment);
- } catch (final StaleStateException staleStateException) {
+ } catch (final ObjectOptimisticLockingFailureException objectOptimisticLockingFailureException) {
failedXpaths.add(dataNodeFragment.getXpath());
}
}
/*
* ============LICENSE_START=======================================================
* Copyright (c) 2021 Bell Canada.
- * Modifications Copyright (C) 2021-2023 Nordix Foundation
+ * Modifications Copyright (C) 2021-2025 OpenInfra Foundation Europe.
* Modifications Copyright (C) 2022-2023 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
package org.onap.cps.ri
import com.fasterxml.jackson.databind.ObjectMapper
-import org.hibernate.StaleStateException
+import org.onap.cps.api.exceptions.ConcurrencyException
import org.onap.cps.api.exceptions.DataNodeNotFoundExceptionBatch
+import org.onap.cps.api.exceptions.DataValidationException
+import org.onap.cps.api.model.DataNode
+import org.onap.cps.api.parameters.FetchDescendantsOption
+import org.onap.cps.impl.DataNodeBuilder
import org.onap.cps.ri.models.AnchorEntity
import org.onap.cps.ri.models.DataspaceEntity
import org.onap.cps.ri.models.FragmentEntity
import org.onap.cps.ri.repository.DataspaceRepository
import org.onap.cps.ri.repository.FragmentRepository
import org.onap.cps.ri.utils.SessionManager
-import org.onap.cps.api.parameters.FetchDescendantsOption
-import org.onap.cps.api.exceptions.ConcurrencyException
-import org.onap.cps.api.exceptions.DataValidationException
-import org.onap.cps.api.model.DataNode
-import org.onap.cps.impl.DataNodeBuilder
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.dao.DataIntegrityViolationException
+import org.springframework.orm.ObjectOptimisticLockingFailureException
import spock.lang.Specification
import java.util.stream.Collectors
def mockFragmentRepository = Mock(FragmentRepository)
def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
def mockSessionManager = Mock(SessionManager)
+ def someCause = Mock(Throwable)
def objectUnderTest = Spy(new CpsDataPersistenceServiceImpl(mockDataspaceRepository, mockAnchorRepository,
mockFragmentRepository, jsonObjectMapper, mockSessionManager))
2 * mockFragmentRepository.save(_)
}
- def 'Handling of StaleStateException (caused by concurrent updates) during patch operation for data nodes.'() {
+ def 'Handling of ObjectOptimisticLockingFailureException (caused by concurrent updates) during patch operation for data nodes.'() {
given: 'the system can update one datanode and has two more datanodes that throw an exception while updating'
def dataNodes = createDataNodesAndMockRepositoryMethodSupportingThem([
'/node1': 'OK',
def updatedLeavesPerXPath = dataNodes.stream()
.collect(Collectors.toMap(DataNode::getXpath, DataNode::getLeaves))
and: 'the batch update will therefore also fail'
- mockFragmentRepository.saveAll(*_) >> { throw new StaleStateException("concurrent updates") }
+ mockFragmentRepository.saveAll(*_) >> { throw new ObjectOptimisticLockingFailureException('concurrent updates', someCause) }
when: 'attempt batch update data nodes'
objectUnderTest.batchUpdateDataLeaves('some-dataspace', 'some-anchor', updatedLeavesPerXPath)
then: 'concurrency exception is thrown'
assert thrown.message == 'DataNode not found'
}
- def 'Handling of StaleStateException (caused by concurrent updates) during update data nodes and descendants.'() {
+ def 'Handling of ObjectOptimisticLockingFailureException (caused by concurrent updates) during update data nodes and descendants.'() {
given: 'the system can update one datanode and has two more datanodes that throw an exception while updating'
def dataNodes = createDataNodesAndMockRepositoryMethodSupportingThem([
'/node1': 'OK',
'/node2': 'EXCEPTION',
'/node3': 'EXCEPTION'])
and: 'the batch update will therefore also fail'
- mockFragmentRepository.saveAll(*_) >> { throw new StaleStateException("concurrent updates") }
+ mockFragmentRepository.saveAll(*_) >> { throw new ObjectOptimisticLockingFailureException('concurrent updates', someCause) }
when: 'attempt batch update data nodes'
objectUnderTest.updateDataNodesAndDescendants('some-dataspace', 'some-anchor', dataNodes)
then: 'concurrency exception is thrown'
def fragmentEntity = new FragmentEntity(xpath: xpath, childFragments: [])
mockFragmentRepository.findByAnchorIdAndXpath(_, xpath) >> fragmentEntity
if ('EXCEPTION' == scenario) {
- mockFragmentRepository.save(fragmentEntity) >> { throw new StaleStateException("concurrent updates") }
+ mockFragmentRepository.save(fragmentEntity) >> { throw new ObjectOptimisticLockingFailureException('concurrent updates', someCause) }
}
return dataNode
}
def fragmentEntity = new FragmentEntity(id: fragmentId, anchor: anchorEntity, xpath: xpath, childFragments: [])
fragmentEntities.add(fragmentEntity)
if ('EXCEPTION' == scenario) {
- mockFragmentRepository.save(fragmentEntity) >> { throw new StaleStateException("concurrent updates") }
+ mockFragmentRepository.save(fragmentEntity) >> { throw new ObjectOptimisticLockingFailureException('concurrent updates', someCause) }
}
fragmentId++
}