50,000 foot overview
I am refactoring a large legacy application to java 17, addressing several generations of technical debt. Part of the refactoring includes swapping out hte defunct bitronix transaction manager for the Narayana + Arjuna combination.
At application launch, Arjuna is failing to start with the exception ARJUNA012391: Could not initialize object store 'null' of type 'com.arjuna.ats.internal.arjuna.objectstore.ShadowNoFileLockStore'
.
Work so far:
I have traced into the ObjectStoreAPI initStore(String name)
to see there is an InvocationTargetException
I have confirmed that:
- the Arjuna environment variables are set to -Duser.dir=C:/arjuna/user -Duser.home=C:/arjuna/user
- the empty object store directories have been created by arjuna, and
- the directory permissions allow the application full control
- the classLoader's reflective calls to the constructor are not prohibited by the visibility
- the unlogged root exception is com.arjuna.ats.arjuna.exceptions.ObjectStoreException: ARJUNA012225: FileSystemStore::setupStore - cannot access root of object store: PutObjectStoreDirHere\ShadowNoFileLockStore\defaultStore\
- The directory C:\arjuna\user\PutObjectStoreDirHere\ShadowNoFileLockStore\defaultStore exists and the jvm has full control of it
Log excerpt:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactoryBean' defined in com.maxis.mxarchive.SchedulerConfig: ARJUNA012391: Could not initialize object store 'null' of type 'com.arjuna.ats.internal.arjuna.objectstore.ShadowNoFileLockStore'
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:709)
... 56 common frames omitted
Caused by: com.arjuna.ats.arjuna.exceptions.FatalError: ARJUNA012391: Could not initialize object store 'null' of type 'com.arjuna.ats.internal.arjuna.objectstore.ShadowNoFileLockStore'
at com.arjuna.ats.arjuna.objectstore.StoreManager.initStore(StoreManager.java:160)
at com.arjuna.ats.arjuna.objectstore.StoreManager.getActionStore(StoreManager.java:111)
at com.arjuna.ats.arjuna.objectstore.StoreManager.getRecoveryStore(StoreManager.java:68)
at com.arjuna.ats.arjuna.recovery.ActionStatusService.<init>(ActionStatusService.java:65)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:306)
at java.base/java.lang.Class.newInstance(Class.java:684)
at com.arjuna.common.internal.util.ClassloadingUtility.loadAndInstantiateClass(ClassloadingUtility.java:135)
at com.arjuna.ats.arjuna.recovery.TransactionStatusManager.start(TransactionStatusManager.java:125)
at com.arjuna.ats.arjuna.recovery.TransactionStatusManager.<init>(TransactionStatusManager.java:58)
at com.arjuna.ats.arjuna.coordinator.TxControl.createTransactionStatusManager(TxControl.java:196)
at com.arjuna.ats.arjuna.coordinator.TxControl.<clinit>(TxControl.java:273)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.begin(BaseTransaction.java:96)
at org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:877)
at org.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:840)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.scheduling.quartz.SchedulerAccessor.registerJobsAndTriggers(SchedulerAccessor.java:209)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:507)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747)
... 66 common frames omitted
Under the covers, the objectStoreDir is computed as a relative path, ignoring the user.dir property, at least in the case of the Windows file system.
Instead of depending on the internal (hidden) directory concatenation, explicitly set the property to an absolute path so as to bypass the "user.dir" system property, something like "-DObjectStoreEnvironmentBean.objectStoreDir=C:/tmp/xyz"