Skip to content

Commit 274df96

Browse files
GH-2193 - Don't roll back the transaction through setRollbackOnly.
Fixes #2193.
1 parent 5bb0097 commit 274df96

File tree

4 files changed

+196
-25
lines changed

4 files changed

+196
-25
lines changed

src/main/java/org/springframework/data/neo4j/core/transaction/Neo4jTransactionHolder.java

-13
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,6 @@ void close() {
9393
session.close();
9494
}
9595

96-
@Override
97-
public void setRollbackOnly() {
98-
99-
super.setRollbackOnly();
100-
transaction.rollback();
101-
}
102-
103-
@Override
104-
public void resetRollbackOnly() {
105-
106-
throw new UnsupportedOperationException();
107-
}
108-
10996
boolean hasActiveSession() {
11097

11198
return session.isOpen();

src/main/java/org/springframework/data/neo4j/core/transaction/ReactiveNeo4jTransactionHolder.java

-12
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,6 @@ Mono<Void> close() {
6969
return Mono.from(session.close());
7070
}
7171

72-
@Override
73-
public void setRollbackOnly() {
74-
75-
super.setRollbackOnly();
76-
}
77-
78-
@Override
79-
public void resetRollbackOnly() {
80-
81-
throw new UnsupportedOperationException();
82-
}
83-
8472
String getDatabaseName() {
8573
return context.getDatabaseName();
8674
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2011-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.imperative;
17+
18+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import org.junit.jupiter.api.BeforeAll;
22+
import org.junit.jupiter.api.Test;
23+
import org.neo4j.driver.Driver;
24+
import org.neo4j.driver.Session;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.dao.InvalidDataAccessResourceUsageException;
29+
import org.springframework.data.neo4j.config.AbstractNeo4jConfig;
30+
import org.springframework.data.neo4j.core.Neo4jClient;
31+
import org.springframework.data.neo4j.integration.shared.common.Person;
32+
import org.springframework.data.neo4j.repository.Neo4jRepository;
33+
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
34+
import org.springframework.data.neo4j.repository.query.Query;
35+
import org.springframework.data.neo4j.test.Neo4jExtension;
36+
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
37+
import org.springframework.transaction.PlatformTransactionManager;
38+
import org.springframework.transaction.annotation.EnableTransactionManagement;
39+
import org.springframework.transaction.annotation.Transactional;
40+
import org.springframework.transaction.support.TransactionTemplate;
41+
42+
/**
43+
* @author Michael J. Simons
44+
*/
45+
@Neo4jIntegrationTest
46+
class Neo4jTransactionManagerTestIT {
47+
48+
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
49+
50+
@BeforeAll
51+
static void clearDatabase() {
52+
try (Session session = neo4jConnectionSupport.getDriver().session()) {
53+
session.writeTransaction(tx -> tx.run("MATCH (n) DETACH DELETE n").consume());
54+
}
55+
}
56+
57+
@Test // GH-2193
58+
void exceptionShouldNotBeShadowed(
59+
@Autowired TransactionTemplate transactionTemplate,
60+
@Autowired Neo4jClient client,
61+
@Autowired SomeRepository someRepository) {
62+
63+
assertThatExceptionOfType(InvalidDataAccessResourceUsageException.class).isThrownBy(() ->
64+
// Need to wrap so that we actually trigger the setRollBackOnly on the outer transaction
65+
transactionTemplate.executeWithoutResult(tx -> {
66+
client.query("CREATE (n:ShouldNotBeThere)").run();
67+
someRepository.broken();
68+
})).withMessageStartingWith("Invalid input 'K'");
69+
70+
try (Session session = neo4jConnectionSupport.getDriver().session()) {
71+
long cnt = session
72+
.readTransaction(tx -> tx.run("MATCH (n:ShouldNotBeThere) RETURN count(n)").single().get(0))
73+
.asLong();
74+
assertThat(cnt).isEqualTo(0L);
75+
}
76+
}
77+
78+
interface SomeRepository extends Neo4jRepository<Person, Long> {
79+
80+
@Transactional // The annotation on the Neo4jRepository is not inherited on the derived methods
81+
@Query("Kaputt")
82+
Person broken();
83+
}
84+
85+
@Configuration
86+
@EnableTransactionManagement
87+
@EnableNeo4jRepositories(considerNestedRepositories = true)
88+
static class Config extends AbstractNeo4jConfig {
89+
90+
@Bean
91+
public Driver driver() {
92+
93+
return neo4jConnectionSupport.getDriver();
94+
}
95+
96+
@Bean
97+
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
98+
return new TransactionTemplate(transactionManager);
99+
}
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright 2011-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.integration.reactive;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import reactor.core.publisher.Mono;
21+
import reactor.test.StepVerifier;
22+
23+
import org.junit.jupiter.api.BeforeAll;
24+
import org.junit.jupiter.api.Test;
25+
import org.neo4j.driver.Driver;
26+
import org.neo4j.driver.Session;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.context.annotation.Bean;
29+
import org.springframework.context.annotation.Configuration;
30+
import org.springframework.dao.InvalidDataAccessResourceUsageException;
31+
import org.springframework.data.neo4j.config.AbstractReactiveNeo4jConfig;
32+
import org.springframework.data.neo4j.core.ReactiveNeo4jClient;
33+
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
34+
import org.springframework.data.neo4j.integration.shared.common.Person;
35+
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
36+
import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories;
37+
import org.springframework.data.neo4j.repository.query.Query;
38+
import org.springframework.data.neo4j.test.Neo4jExtension;
39+
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
40+
import org.springframework.transaction.annotation.EnableTransactionManagement;
41+
import org.springframework.transaction.reactive.TransactionalOperator;
42+
43+
/**
44+
* @author Michael J. Simons
45+
*/
46+
@Neo4jIntegrationTest
47+
class ReactiveNeo4jTransactionManagerTestIT {
48+
49+
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
50+
51+
@BeforeAll
52+
static void clearDatabase() {
53+
try (Session session = neo4jConnectionSupport.getDriver().session()) {
54+
session.writeTransaction(tx -> tx.run("MATCH (n) DETACH DELETE n").consume());
55+
}
56+
}
57+
58+
@Test // GH-2193
59+
void exceptionShouldNotBeShadowed(
60+
@Autowired ReactiveNeo4jTransactionManager transactionManager,
61+
@Autowired ReactiveNeo4jClient client,
62+
@Autowired SomeRepository someRepository) {
63+
64+
TransactionalOperator rxtx = TransactionalOperator.create(transactionManager);
65+
66+
rxtx.execute(txStatus -> client.query("CREATE (n:ShouldNotBeThere)").run()
67+
.then(someRepository.broken().as(rxtx::transactional))
68+
).then().as(StepVerifier::create).verifyError(InvalidDataAccessResourceUsageException.class);
69+
70+
try (Session session = neo4jConnectionSupport.getDriver().session()) {
71+
long cnt = session
72+
.readTransaction(tx -> tx.run("MATCH (n:ShouldNotBeThere) RETURN count(n)").single().get(0))
73+
.asLong();
74+
assertThat(cnt).isEqualTo(0L);
75+
}
76+
}
77+
78+
interface SomeRepository extends ReactiveNeo4jRepository<Person, Long> {
79+
80+
@Query("Kaputt")
81+
Mono<Person> broken();
82+
}
83+
84+
@Configuration
85+
@EnableTransactionManagement
86+
@EnableReactiveNeo4jRepositories(considerNestedRepositories = true)
87+
static class Config extends AbstractReactiveNeo4jConfig {
88+
89+
@Bean
90+
public Driver driver() {
91+
92+
return neo4jConnectionSupport.getDriver();
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)