ModeShape not commiting using Atomikos and Spring
singhl1 Jun 19, 2013 4:10 AMWe have the following scenario, Tomcat 6.0.37, Spring 3.1, ModeShape 3.3.0, and i have the follwoing problem, if i add node to the repository workspace, they are visibe on the web screen i add them through. I am adding an nt:folder node to an existing nt:folder in the workspace. If i naviate away from the web page and back to the same web page the newly added node is no longer there, it seems as though my new node has not been commited to the repository (or rolled back by atomikos???)
My config is as follows:
dataRepository.json
{
"name": "Repository",
"jndiName": "",
"workspaces": {
"predefined": ["Library"],
"default": "Library",
"allowCreation": true
},
"security": {
"anonymous": {
"roles": ["readonly", "readwrite", "admin"],
"useOnFailedLogin": false
}
},
"storage": {
"cacheName": "Repository",
"binaryStorage": {
"type": "file",
"directory": "/repo/Library/binaries"
}
},
"query": {
"enabled": true,
"enableFullTextSearch": true,
"indexStorage": {
"type" : "filesystem",
"location" : "/repo/Library/indexes",
"lockingStrategy" : "simple",
"fileSystemAccessType" : "auto"
},
"indexing" : {
"rebuildOnStartup": {
"includeSystemContent": true,
"mode" : "sync"
}
},
"textExtracting": {
"extractors": {
"tikaExtractor": {
"name": "Tika content-based extractor",
"classname": "tika"
}
}
}
},
"sequencing": {
"removeDerivedContentWithOriginal": true,
"sequencers": {
"Images in separate location": {
"classname": "ImageSequencer",
"pathExpression": "Library://(*.(gif|png|pict|jpg))/jcr:content[@jcr:data] => Library:/sequenced/images"
}
}
},
"node-types" : ["common_mixin.cnd"]
}
I am extending RepositoryFactoryBean in java as follows:
import java.util.concurrent.Future;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.modeshape.common.collection.Problems;
import org.modeshape.jcr.RepositoryConfiguration;
import org.springframework.extensions.jcr.RepositoryFactoryBean;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.transaction.LockingMode;
import org.infinispan.transaction.TransactionMode;
import org.modeshape.jcr.LocalEnvironment;
import org.modeshape.jcr.ModeShapeEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
public class ModeShapeRepositoryFactoryBean extends RepositoryFactoryBean {
private final static Log log = LogFactory.getLog(ModeShapeRepositoryFactoryBean.class);
@Value("${modeshape.jsonfile}")
private Resource jcrconfigresource;
@Value("${modeshape.defaultworkspace}")
private String modeshapeDefaultworkspace;
@Autowired
private ModeShapeEngine engine;
@Autowired
private GetInfinispanTransactionmanager getInfinispanTransactionmanager;
private RepositoryConfiguration repositoryConfiguration;
@Override
protected void resolveConfigurationResource() throws Exception {
log.debug("resolveConfigurationResource - start");
if (repository == null) {
try {
repositoryConfiguration = RepositoryConfiguration.read(jcrconfigresource.getFile());
ConfigurationBuilder builder = new ConfigurationBuilder();
Configuration cacheConfig =
builder
.transaction()
.transactionManagerLookup(getInfinispanTransactionmanager)
.transactionMode(TransactionMode.TRANSACTIONAL)
// .autoCommit(true)
.lockingMode(LockingMode.PESSIMISTIC)
.loaders()
.passivation(false)
.shared(false)
.preload(false)
.addFileCacheStore().async().threadPoolSize(10).enabled(true)
.fetchPersistentState(false)
.purgeOnStartup(false)
.addProperty("location", "/repo/Library/content")
.build();
LocalEnvironment environment = new LocalEnvironment();
environment.defineCache("Repository", cacheConfig); // Must match the cacheName property in your modeshape config
if (repositoryConfiguration == null) {
repositoryConfiguration = RepositoryConfiguration.read(jcrconfigresource.getFile());
}
repositoryConfiguration = repositoryConfiguration.with(environment);
} catch (Throwable e) {
log.error(e);
}
log.debug("resolveConfigurationResource - end");
}
}
@Override
public Repository getObject() throws Exception {
return this.repository;
}
@Override
protected Repository createRepository() throws Exception {
log.debug("createRepository - start");
if (repository == null) {
try {
if (repositoryConfiguration == null) {
resolveConfigurationResource();
}
engine.start();
// Verify the configuration for the repository ...
Problems problems = repositoryConfiguration.validate();
if (problems.hasErrors()) {
log.error("Problems starting the engine.");
log.error(problems);
}
repository = engine.deploy(repositoryConfiguration);
engine.start();
Session session = repository.login(modeshapeDefaultworkspace);
Node root = session.getRootNode();
try {
Node library = session.getNode("/Library");
} catch (PathNotFoundException e){
root.addNode("Library", "nt:folder");
} catch (RepositoryException e){
root.addNode("Library", "nt:folder");
}
session.save();
session.logout();
} catch (Throwable e) {
log.error(e);
}
}
return repository;
}
@Override
public void destroy() throws Exception {
Future<Boolean> future = engine.undeploy(repositoryConfiguration.getName());
if (future.get()) {
log.debug("Undeployed " + repositoryConfiguration.getName() + repositoryConfiguration.getName());
}
future = engine.shutdown();
if (future.get()) { // optional, but blocks until engine is completely shutdown or interrupted
log.debug("Shut down ModeShape");
}
}
}
The transactionmanager is retrieved by the following code:
import javax.transaction.TransactionManager;
import org.infinispan.transaction.lookup.TransactionManagerLookup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.jta.JtaTransactionManager;
public class GetInfinispanTransactionmanager implements TransactionManagerLookup {
@Autowired
JtaTransactionManager JtaTransactionManager;
@Override
public TransactionManager getTransactionManager() throws Exception {
return JtaTransactionManager.getTransactionManager();
}
}
My atomikos cofig is as follows in spring:
<beans:bean id="userTransactionService"
class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce" depends-on="setMyAtomikosSystemProps">
<beans:constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<beans:props>
<beans:prop key="com.atomikos.icatch.service">
com.atomikos.icatch.standalone.UserTransactionServiceFactory
</beans:prop>
</beans:props>
</beans:constructor-arg>
</beans:bean>
<!--
Construct Atomikos UserTransactionManager,
needed to configure Spring
-->
<beans:bean id="AtomikosTransactionManager"
class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close"
depends-on="userTransactionService,setMyAtomikosSystemProps">
<!-- IMPORTANT: disable startup because the userTransactionService above does this -->
<beans:property name="startupTransactionService" value="false"/>
<!--
when close is called,
should we force transactions to terminate or not?
-->
<beans:property name="forceShutdown" value="false" />
</beans:bean>
<!--
Also use Atomikos UserTransactionImp,
needed to configure Spring
-->
<beans:bean id="AtomikosUserTransaction"
class="com.atomikos.icatch.jta.UserTransactionImp"
depends-on="userTransactionService,setMyAtomikosSystemProps">
<beans:property name="transactionTimeout" value="300" />
</beans:bean>
<!--
Configure the Spring framework to use JTA transactions from Atomikos
-->
<beans:bean id="JtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="userTransactionService,setMyAtomikosSystemProps">
<beans:property name="transactionManager" ref="AtomikosTransactionManager" />
<beans:property name="userTransaction" ref="AtomikosUserTransaction" />
</beans:bean>
<tx:annotation-driven transaction-manager="JtaTransactionManager" />
<beans:bean id="setMyAtomikosSystemProps"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<beans:property name="targetObject">
<!-- System.getProperties() -->
<beans:bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<beans:property name="targetClass" value="java.lang.System" />
<beans:property name="targetMethod" value="getProperties" />
</beans:bean>
</beans:property>
<beans:property name="targetMethod" value="putAll" />
<beans:property name="arguments">
<!-- The new Properties -->
<util:properties>
<beans:prop key="com.atomikos.icatch.file">jta.properties</beans:prop>
<beans:prop key="com.atomikos.icatch.hide_init_file_path">true</beans:prop>
</util:properties>
</beans:property>
</beans:bean>
The transactiona are annotated with @Transactional("JtaTransactionManager")
My jta.properties are:
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name = tm.out
com.atomikos.icatch.console_file_limit=-1
com.atomikos.icatch.output_dir = ./
com.atomikos.icatch.log_base_dir = ./
com.atomikos.icatch.log_base_name = tmlog
com.atomikos.icatch.max_actives = -1
com.atomikos.icatch.default_jta_timeout = 100000
com.atomikos.icatch.max_timeout = 300000
com.atomikos.icatch.tm_unique_name = tm
For some reason any updates to the repository are not persisted, my thinking is that the ModeShapeRepositoryFactoryBean ConfigurationBuilder code is not correct, if i set the transaction to autocommit off i get execeptions thrown if the repository is added to. The strange thing is while i add to the repository in a web page all changes are visible, but when i navigate away and back to the same page, the changes have disappeared (rolled back?).....