Skip to content
This repository has been archived by the owner on Sep 20, 2021. It is now read-only.

Commit

Permalink
Merge branch '2.8.0'
Browse files Browse the repository at this point in the history
* 2.8.0:
  Bumped spring dependency to 4.0.4
  More fine-grained synchronization in DynamicRepositoryManagerConnectionFactory
  Updated tests
  Added isolation support

Conflicts:
	pom.xml
  • Loading branch information
ameingast committed Feb 21, 2015
2 parents 8216952 + f2bc874 commit fe521d3
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 137 deletions.
18 changes: 12 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-spring</artifactId>
<version>2.7.13</version>

<version>2.8.0-beta1</version>
<name>${project.artifactId}</name>

<description>
Expand All @@ -28,6 +29,11 @@
<connection>scm:git:https://github.com/ameingast/sesame-spring.git</connection>
</scm>

<issueManagement>
<system>Github</system>
<url>https://github.com/ameingast/sesame-spring/issues</url>
</issueManagement>

<licenses>
<license>
<name>Apache License 2.0</name>
Expand Down Expand Up @@ -82,14 +88,14 @@
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-queryparser-sparql</artifactId>
<artifactId>sesame-repository-sail</artifactId>
<version>${sesame.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-repository-sail</artifactId>
<artifactId>sesame-queryparser-sparql</artifactId>
<version>${sesame.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import org.openrdf.repository.manager.RepositoryManager;
import org.springframework.beans.factory.DisposableBean;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* <p>{@link RepositoryManagerConnectionFactory} handles connections to a multiple corresponding
Expand Down Expand Up @@ -53,7 +53,7 @@ public DynamicRepositoryManagerConnectionFactory(RepositoryManager repositoryMan
this.repositoryManager = repositoryManager;
this.repositoryImplConfig = repositoryImplConfig;
this.repositoryIdProvider = repositoryIdProvider;
this.repositoryConnectionFactoryMap = new ConcurrentHashMap<String, RepositoryConnectionFactory>(128);
this.repositoryConnectionFactoryMap = new HashMap<String, RepositoryConnectionFactory>(128);
}

/**
Expand Down Expand Up @@ -96,7 +96,7 @@ public SesameTransactionObject getLocalTransactionObject() {
return getRepositoryConnectionFactory().getLocalTransactionObject();
}

private RepositoryConnectionFactory getRepositoryConnectionFactory() {
private synchronized RepositoryConnectionFactory getRepositoryConnectionFactory() {
String repositoryId = repositoryIdProvider.getRepositoryId();
RepositoryConnectionFactory repositoryConnectionFactory = repositoryConnectionFactoryMap.get(repositoryId);

Expand All @@ -109,12 +109,6 @@ private RepositoryConnectionFactory getRepositoryConnectionFactory() {
}

private RepositoryConnectionFactory initializeRepositoryConnectionFactory(String repositoryId) {
RepositoryConnectionFactory repositoryConnectionFactory = repositoryConnectionFactoryMap.get(repositoryId);

if (repositoryConnectionFactory != null) {
return repositoryConnectionFactory;
}

try {
Repository repository = repositoryManager.getRepository(repositoryId);

Expand Down
44 changes: 44 additions & 0 deletions src/main/java/org/openrdf/spring/IsolationLevelAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.openrdf.spring;

import org.openrdf.IsolationLevel;
import org.openrdf.IsolationLevels;
import org.openrdf.sail.Sail;
import org.springframework.transaction.InvalidIsolationLevelException;
import org.springframework.transaction.TransactionDefinition;

/**
* <p>Adapter to convert spring {@link TransactionDefinition} isolation levels to corresponding OpenRDF
* {@link org.openrdf.IsolationLevel}s.</p>
* <p/>
* <p>The conversion depends on the provided {@link org.openrdf.sail.Sail} and its transaction capabilities.
* If the {@link org.openrdf.sail.Sail} is not compatible with the provided isolation level, an
* {@link org.springframework.transaction.InvalidIsolationLevelException} is thrown.<p/>
*
* @author ameingast@gmail.com
*/
class IsolationLevelAdapter {
static IsolationLevel adaptToRdfIsolation(Sail sail, int springIsolation) {
switch (springIsolation) {
case TransactionDefinition.ISOLATION_DEFAULT:
return sail.getDefaultIsolationLevel();
case TransactionDefinition.ISOLATION_READ_COMMITTED:
return determineIsolationLevel(sail, IsolationLevels.READ_COMMITTED);
case TransactionDefinition.ISOLATION_READ_UNCOMMITTED:
return determineIsolationLevel(sail, IsolationLevels.READ_UNCOMMITTED);
case TransactionDefinition.ISOLATION_REPEATABLE_READ:
throw new InvalidIsolationLevelException("Unsupported isolation level for sail: " + sail + ": " + springIsolation);
case TransactionDefinition.ISOLATION_SERIALIZABLE:
return determineIsolationLevel(sail, IsolationLevels.SERIALIZABLE);
default:
throw new InvalidIsolationLevelException("Unsupported isolation level for sail: " + sail + ": " + springIsolation);
}
}

private static IsolationLevel determineIsolationLevel(Sail sail, IsolationLevel isolationLevel) {
if (sail.getSupportedIsolationLevels().contains(isolationLevel)) {
return isolationLevel;
} else {
throw new InvalidIsolationLevelException("Unsupported isolation level for sail: " + sail + ": " + isolationLevel);
}
}
}
17 changes: 7 additions & 10 deletions src/main/java/org/openrdf/spring/RepositoryConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public RepositoryConnection getConnection() {
}

if (!repositoryConnection.isActive()) {
throw new SesameTransactionException("No transaction active");
repositoryConnection.begin();
}
} catch (RepositoryException e) {
throw new SesameTransactionException(e);
Expand Down Expand Up @@ -102,7 +102,6 @@ public void closeConnection() {
@Override
public SesameTransactionObject createTransaction() throws RepositoryException {
RepositoryConnection repositoryConnection = repository.getConnection();
repositoryConnection.begin();

SesameTransactionObject sesameTransactionObject = new SesameTransactionObject(repositoryConnection);
localTransactionObject.set(sesameTransactionObject);
Expand All @@ -127,14 +126,12 @@ public void endTransaction(boolean rollback) throws RepositoryException {
throw new SesameTransactionException("Connection closed during transaction");
}

if (!repositoryConnection.isActive()) {
throw new SesameTransactionException("No transaction active");
}

if (rollback) {
repositoryConnection.rollback();
} else {
repositoryConnection.commit();
if (repositoryConnection.isActive()) {
if (rollback) {
repositoryConnection.rollback();
} else {
repositoryConnection.commit();
}
}
}

Expand Down
33 changes: 27 additions & 6 deletions src/main/java/org/openrdf/spring/SesameTransactionManager.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package org.openrdf.spring;

import org.openrdf.IsolationLevel;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.sail.Sail;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;

import static org.openrdf.spring.IsolationLevelAdapter.adaptToRdfIsolation;

/**
* <p>{@link SesameTransactionManager} manages the transaction lifecycle of a {@link SesameTransactionObject}.</p>
* <p/>
Expand Down Expand Up @@ -65,14 +72,28 @@ protected boolean isExistingTransaction(Object transaction) throws TransactionEx
* {@see AbstractPlatformTransactionManager#doBegin}
*/
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
protected void doBegin(Object transaction, TransactionDefinition transactionDefinition) throws TransactionException {
SesameTransactionObject sesameTransactionObject = (SesameTransactionObject) transaction;

sesameTransactionObject.setTimeout(definition.getTimeout());
sesameTransactionObject.setIsolationLevel(definition.getIsolationLevel());
sesameTransactionObject.setPropagationBehavior(definition.getPropagationBehavior());
sesameTransactionObject.setReadOnly(definition.isReadOnly());
sesameTransactionObject.setName("[" + Thread.currentThread().getName() + "] " + definition.getName());
sesameTransactionObject.setTimeout(transactionDefinition.getTimeout());
sesameTransactionObject.setIsolationLevel(transactionDefinition.getIsolationLevel());
sesameTransactionObject.setPropagationBehavior(transactionDefinition.getPropagationBehavior());
sesameTransactionObject.setReadOnly(transactionDefinition.isReadOnly());
sesameTransactionObject.setName(Thread.currentThread().getName() + " " + transactionDefinition.getName());

setIsolationLevel(sesameTransactionObject, transactionDefinition);
}

private void setIsolationLevel(SesameTransactionObject sesameTransactionObject, TransactionDefinition transactionDefinition) {
RepositoryConnection repositoryConnection = sesameTransactionObject.getRepositoryConnection();
Repository repository = repositoryConnection.getRepository();

if (repository instanceof SailRepository) {
Sail sail = ((SailRepository) repository).getSail();
IsolationLevel isolationLevel = adaptToRdfIsolation(sail, transactionDefinition.getIsolationLevel());

repositoryConnection.setIsolationLevel(isolationLevel);
}
}

/**
Expand Down
69 changes: 69 additions & 0 deletions src/test/java/org/openrdf/spring/BaseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.openrdf.spring;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.openrdf.model.URI;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/repositoryTestContext.xml")
public abstract class BaseTest {
@Autowired
protected SesameConnectionFactory repositoryConnectionFactory;

@Autowired
protected SesameConnectionFactory repositoryManagerConnectionFactory;

protected static void assertDataPresent(SesameConnectionFactory sesameConnectionFactory) throws Exception {
RepositoryConnection connection = sesameConnectionFactory.getConnection();
final TupleQuery tupleQuery = connection.prepareTupleQuery(QueryLanguage.SPARQL, "SELECT ?s ?o WHERE { ?s <http://example.com/b> ?o . }");
TupleQueryResult result = tupleQuery.evaluate();

withTupleQueryResult(result, new TupleQueryResultHandler() {
@Override
public void handle(TupleQueryResult tupleQueryResult) throws Exception {
Assert.assertTrue(tupleQueryResult.hasNext());

BindingSet bindingSet = tupleQueryResult.next();

Assert.assertEquals("http://example.com/a", bindingSet.getBinding("s").getValue().stringValue());
Assert.assertEquals("http://example.com/c", bindingSet.getBinding("o").getValue().stringValue());
}
});
}

private static void withTupleQueryResult(TupleQueryResult tupleQueryResult,
TupleQueryResultHandler tupleQueryResultHandler) throws Exception {
try {
tupleQueryResultHandler.handle(tupleQueryResult);
} finally {
tupleQueryResult.close();
}
}

protected static void addData(SesameConnectionFactory sesameConnectionFactory) throws RepositoryException {
ValueFactory f = ValueFactoryImpl.getInstance();
URI a = f.createURI("http://example.com/a");
URI b = f.createURI("http://example.com/b");
URI c = f.createURI("http://example.com/c");

RepositoryConnection connection = sesameConnectionFactory.getConnection();
connection.add(a, b, c);
}

static interface TupleQueryResultHandler {
void handle(TupleQueryResult tupleQueryResult) throws Exception;
}
}
Loading

0 comments on commit fe521d3

Please sign in to comment.