DataIntegrityViolation exception in Integration Test

cancel
Showing results for 
Search instead for 
Did you mean: 
ilseva
Active Member

DataIntegrityViolation exception in Integration Test

Hi,

we are developing an extension of alfresco to manage custom models.  Version 7.0.0, SDK 4.2.

We needed an extesion of Site to store extra properties, so we define our custom type Project.

Then, we extend the SiteServiceImpl to inherit all Site business logic and configure the bean in service-context.xml.

Sometimes, the integration tests fails with this message:

org.springframework.dao.DataIntegrityViolationException: Detected stale node entry: NodeVersionKey [nodeId=32, version=12] (now NodeVersionKey [nodeId=32, version=13])

This is the complete stacktrace (I cut some lines due to the message limit)

org.springframework.dao.DataIntegrityViolationException: Detected stale node entry: NodeVersionKey [nodeId=32, version=12] (now NodeVersionKey [nodeId=32, version=13])
[33medi-acs_1 |[0m at org.alfresco.repo.domain.node.AbstractNodeDAOImpl.loadParentAssocs(AbstractNodeDAOImpl.java:4418)
[33medi-acs_1 |[0m at org.alfresco.repo.domain.node.AbstractNodeDAOImpl.getParentAssocsCached(AbstractNodeDAOImpl.java:4311)
[33medi-acs_1 |[0m at org.alfresco.repo.domain.node.AbstractNodeDAOImpl.newChildAssoc(AbstractNodeDAOImpl.java:3194)
[33medi-acs_1 |[0m at org.alfresco.repo.node.db.DbNodeServiceImpl.addChild_aroundBody46(DbNodeServiceImpl.java:1320)
[33medi-acs_1 |[0m at org.alfresco.repo.node.db.DbNodeServiceImpl$AjcClosure47.run(DbNodeServiceImpl.java:1)
[33medi-acs_1 |[0m at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:167)
[33medi-acs_1 |[0m at org.alfresco.traitextender.RouteExtensions.intercept(RouteExtensions.java:100)
[33medi-acs_1 |[0m at org.alfresco.repo.node.db.DbNodeServiceImpl.addChild(DbNodeServiceImpl.java:1293)
[33medi-acs_1 |[0m at jdk.internal.reflect.GeneratedMethodAccessor450.invoke(Unknown Source)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[33medi-acs_1 |[0m at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[33medi-acs_1 |[0m at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
[33medi-acs_1 |[0m at org.alfresco.repo.lock.mem.LockableAspectInterceptor.invoke(LockableAspectInterceptor.java:244)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
[33medi-acs_1 |[0m at com.sun.proxy.$Proxy32.addChild(Unknown Source)
[33medi-acs_1 |[0m at jdk.internal.reflect.GeneratedMethodAccessor450.invoke(Unknown Source)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[33medi-acs_1 |[0m at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[33medi-acs_1 |[0m at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
[33medi-acs_1 |[0m at org.alfresco.repo.tenant.MultiTNodeServiceInterceptor.invoke(MultiTNodeServiceInterceptor.java:111)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
[33medi-acs_1 |[0m at com.sun.proxy.$Proxy32.addChild(Unknown Source)
[33medi-acs_1 |[0m at jdk.internal.reflect.GeneratedMethodAccessor450.invoke(Unknown Source)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[33medi-acs_1 |[0m at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[33medi-acs_1 |[0m at org.alfresco.repo.service.StoreRedirectorProxyFactory$RedirectorInvocationHandler.invoke(StoreRedirectorProxyFactory.java:231)
[33medi-acs_1 |[0m at com.sun.proxy.$Proxy48.addChild(Unknown Source)
[33medi-acs_1 |[0m at org.alfresco.repo.security.authority.AuthorityDAOImpl.addAuthority(AuthorityDAOImpl.java:369)
[33medi-acs_1 |[0m at org.alfresco.repo.security.authority.AuthorityServiceImpl.addAuthority(AuthorityServiceImpl.java:485)
[33medi-acs_1 |[0m at org.alfresco.repo.security.authority.AuthorityServiceImpl.addAuthority(AuthorityServiceImpl.java:477)
[33medi-acs_1 |[0m at org.alfresco.repo.site.SiteServiceImpl$3.doWork(SiteServiceImpl.java:722)
[33medi-acs_1 |[0m at org.alfresco.repo.site.SiteServiceImpl$3.doWork(SiteServiceImpl.java:1)
[33medi-acs_1 |[0m at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:602)
[33medi-acs_1 |[0m at org.alfresco.repo.site.SiteServiceImpl.setupSitePermissions(SiteServiceImpl.java:626)
[33medi-acs_1 |[0m at org.alfresco.repo.site.SiteServiceImpl.setupSitePermissions(SiteServiceImpl.java:616)
[33medi-acs_1 |[0m at org.alfresco.repo.site.SiteServiceImpl.createSite(SiteServiceImpl.java:584)
[33medi-acs_1 |[0m at com.stamtech.edi.services.ProjectServiceImpl.createProject(ProjectServiceImpl.java:234)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[33medi-acs_1 |[0m at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[33medi-acs_1 |[0m at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[33medi-acs_1 |[0m at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
[33medi-acs_1 |[0m at net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:80)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:53)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:166)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.alfresco.repo.transaction.CheckTransactionAdvice.invoke(CheckTransactionAdvice.java:54)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.alfresco.repo.transaction.RetryingTransactionAdvice$1.execute(RetryingTransactionAdvice.java:71)
[33medi-acs_1 |[0m at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:450)
[33medi-acs_1 |[0m at org.alfresco.repo.transaction.RetryingTransactionAdvice.invoke(RetryingTransactionAdvice.java:74)
[33medi-acs_1 |[0m at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
[33medi-acs_1 |[0m at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
[33medi-acs_1 |[0m at com.sun.proxy.$Proxy169.createProject(Unknown Source)
[33medi-acs_1 |[0m at com.stamtech.edi.test.utils.MockProject$1.execute(MockProject.java:43)
[33medi-acs_1 |[0m at com.stamtech.edi.test.utils.MockProject$1.execute(MockProject.java:41)
[33medi-acs_1 |[0m at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:450)
[33medi-acs_1 |[0m at com.stamtech.edi.test.utils.MockProject.createProject(MockProject.java:49)
[33medi-acs_1 |[0m at com.stamtech.edi.test.behaviors.ProjectBehaviorIT.whenCreateProjectThenCheckFolders(ProjectBehaviorIT.java:34)
...

In our tests we create Project using the RetryingTransactionCallback, but the exception is thrown even if we don't use this class.

RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>() {
            public NodeRef execute() throws Throwable {
                ProjectResource createdProjectResource = projectService.createProject(projectResource);
                return createdProjectResource.getNodeRef();
            }
        };
        try {
            RetryingTransactionHelper transactionHelper = transactionService.getRetryingTransactionHelper();
            NodeRef projectRef = transactionHelper.doInTransaction(callback);
            return projectRef;
        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }

what goes wrong?

Thanks,

Sevastian

 

2 Replies
afaust
Master

Re: DataIntegrityViolation exception in Integration Test

Without knowing what you are doing precisely in your extended SiteService, and also what kind of operations are done in the test before that point, it is impossible to say what is causing the data integrity violation. Usually this is a sign of some operation not properly updating / removing a cache entry after a modification has taken place

ilseva
Active Member

Re: DataIntegrityViolation exception in Integration Test

Hi, thanks for you reply.

This is the test method

@RunWith(value = AlfrescoTestRunner.class)
public class ProjectBehaviorIT extends AbstractAlfrescoIT {
@Test public void whenCreateProjectThenCheckFolders() { NodeRef projectNodeRef = MockProject.createProject(getApplicationContext(), "TEST", false); Assert.assertNotNull(projectNodeRef);
... }

 This is the MockProject utils method

public static NodeRef createProject(ApplicationContext context, String projectName, boolean newTransaction) {
        TransactionService transactionService = (TransactionService) context.getBean("transactionService");
        ProjectService projectService = (ProjectService) context.getBean("projectService");
        String adminUserName = AuthenticationUtil.getAdminUserName();
        AuthenticationUtil.setFullyAuthenticatedUser(adminUserName);
        final ProjectResource projectResource = new ProjectResource();
        projectResource.setProjectName(projectName);
        LocalDate startDate = LocalDate.now();
        projectResource.setProjectStartDate(Date.from(startDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
        projectResource.setProjectEndDate(Date.from(startDate.plusYears(1).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
        projectResource.setProjectVisibility("private");
        
        RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>() {
            public NodeRef execute() throws Throwable {
                ProjectResource createdProjectResource = projectService.createProject(projectResource);
                return createdProjectResource.getNodeRef();
            }
        };
        try {
            RetryingTransactionHelper transactionHelper = transactionService.getRetryingTransactionHelper();
            NodeRef projectRef = transactionHelper.doInTransaction(callback, false, newTransaction);
            return projectRef;
        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }
    }

Finally this is the ProjectServiceImpl that extends SiteServiceImpl

public class ProjectServiceImpl extends SiteServiceImpl implements ProjectService {
....
 @Override
    public ProjectResource createProject(ProjectResource project) {
        QName nodeType = QName.createQName(EdiModel.EDI_MODEL_URI, EdiModel.TYPE_EDI_PROJECT);
            
            SiteInfo ediSite = createSite(EdiModel.TYPE_EDI_PROJECT
                , project.getProjectName()
                , project.getProjectName()
                , project.getProjectDescription()
                , setProjectVisibility(project.getProjectVisibility())
                , nodeType);

            project.setProjectStatus(ProjectStatus.RELEASE_0.getLabel());

            try {
                Map<QName, Serializable> defaultSiteProperties = nodeService.getProperties(ediSite.getNodeRef());
                defaultSiteProperties.putAll(setProjectProperties(project));
                nodeService.setProperties(ediSite.getNodeRef(), defaultSiteProperties);
                
                /** we clear the inherited permissions from the project, which is the node parent, and set up 
                 * specific local permissions for the folder BuildingSite
                 * 
                 * REMARK: IF WE CHANGE THE BEHAVIOUR POLICY FOR THE EVENT "onCreateNode" ( ProjectBehaviour.java) CHECK OUT THE FOLDER BUILDINGSITE 
                 * IS AVAILABLE AND THE LOCAL PERMISSIONS ARE SET UP CORRECTLY */
                NodeRef buildingSiteFolder = nodeService.getChildByName(ediSite.getNodeRef(), ContentModel.ASSOC_CONTAINS, EdiModel.FOLDER_BUILDING_SITE_DOCS);
                permissionService.setInheritParentPermissions(buildingSiteFolder, false);
                setLocalPermissionsOnFolder(buildingSiteFolder, ediSite.getNodeRef());
                
                project.setNodeRef(ediSite.getNodeRef());
                project.setId(ediSite.getShortName());

                return project;
            } catch (InvalidNodeRefException ex) {
                throw new SiteServiceException("Impossible to create the project");
            }
    }

We have a behavior defined for onCreateNode event thats create default folders inside Project.

Thanks for support.