在处理来自 @Index(unique=true) 的 ClientException 后,对 Neo4j 的所有后续调用都会冻结

All subsequent calls to Neo4j freezes after handling a ClientException from @Index(unique=true)

我有一个 Spring 启动应用程序,它有一个在字段上具有唯一性约束的实体。

im 运行ning spring-boot, spring-data-neo4j, neo4j-ogm, bolt-driver 和 neo4j 3.2 docker 镜像。

当我 运行 我的 IT 测试时,我首先保留一些数据,然后我尝试保留相同的数据以触发约束。

唯一性约束按预期启动并抛出 ClientException。这被捕获并向客户端返回适当的异常。

然后在下面的测试中,我只是尝试保存一些数据,当它 运行 在 GraphRepository 中执行 save() 时,服务器突然冻结。

所以我的问题是,为什么在我的案例中,由于唯一性约束已被抛出 ClientException 后,neo4j 在所有后续事务中完全冻结。日志什么也没说,neo4j debug.log什么都没说

如果我 运行 每个测试分开,它们都会通过。 运行一起,在测试完containt之后,它在测试中冻结了neo4j。

pom.xml

<?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"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<groupId>se.andolf</groupId>
<artifactId>lift</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>

<modules>
    <module>lift-api</module>
    <module>lift-service</module>
    <module>lift-app</module>
</modules>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring.boot.version>1.5.3.RELEASE</spring.boot.version>
    <spring-data-releasetrain.version>Ingalls-SR3</spring-data-releasetrain.version>
    <neo4j-ogm.version>2.1.2</neo4j-ogm.version>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
</parent>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>Ingalls-SR3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>se.andolf</groupId>
            <artifactId>lift-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>se.andolf</groupId>
            <artifactId>lift-common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>se.andolf</groupId>
            <artifactId>lift-service</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-core</artifactId>
            <version>${neo4j-ogm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-bolt-driver</artifactId>
            <version>${neo4j-ogm.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.jmnarloch</groupId>
            <artifactId>modelmapper-spring-boot-starter</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.uuid</groupId>
            <artifactId>java-uuid-generator</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.fge</groupId>
            <artifactId>json-patch</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring.boot.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>3.0.3</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.18.1</version>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.11</version>
            </plugin>
        </plugins>
    </pluginManagement>

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>integration-tests</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>0.7.7.201606060606</version>
                    <executions>
                        <execution>
                            <id>default-prepare-agent</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>default-prepare-agent-integration</id>
                            <goals>
                                <goal>prepare-agent-integration</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>default-report</id>
                            <goals>
                                <goal>report</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>default-report-integration</id>
                            <goals>
                                <goal>report-integration</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>coveralls</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.eluder.coveralls</groupId>
                    <artifactId>coveralls-maven-plugin</artifactId>
                    <version>4.3.0</version>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

lift-service/pom.xml

<?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"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
    <artifactId>lift</artifactId>
    <groupId>se.andolf</groupId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>lift-service</artifactId>
<packaging>jar</packaging>

<dependencies>
    <dependency>
        <groupId>se.andolf</groupId>
        <artifactId>lift-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-neo4j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-ogm-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-ogm-bolt-driver</artifactId>
    </dependency>
    <dependency>
        <groupId>com.github.fge</groupId>
        <artifactId>json-patch</artifactId>
    </dependency>
    <dependency>
        <groupId>com.github.jmnarloch</groupId>
        <artifactId>modelmapper-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

会话 bean 配置:

@Configuration
@EnableNeo4jRepositories(basePackages = "se.andolf")
@EnableTransactionManagement
public class SessionConfig {

    @Bean
    public SessionFactory sessionFactory(){
        LOG.debug("Loading session factory");
        return new SessionFactory("se.andolf");
    }

    @Bean
    public Neo4jTransactionManager transactionManager() {
        return new Neo4jTransactionManager(sessionFactory());
    }
}

CategoryController.class

@RestController
@Api(tags = { "Categories" })
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    @RequestMapping(method=PUT, value="/categories")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Void> add(
        @RequestBody Category category, HttpServletRequest request) throws URISyntaxException {
        final Long id = categoryService.save(category);
        final HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setLocation(new URI(request.getRequestURL().toString() + "/" + id));
        return new ResponseEntity<>(responseHeaders, HttpStatus.CREATED);
    }
}

CategoryService.class

@Service
@Transactional
public class CategoryService {
    private static Log LOG = LogFactory.getLog(CategoryService.class);

    @Autowired
    private CategoryRepository categoryRepository;

    public Long save(Category category){
        final CategoryEntity categoryEntity = new CategoryEntity(category.getName());

        try {
            return categoryRepository.save(categoryEntity).getId();
        } catch (ClientException e) {
            LOG.error("Category " + category.getName() + " exists select another name", e);
            throw new NodeExistsException("Category " + category.getName() + " exists please select another name");
        }
    }
}

CategoryEntity.class

@NodeEntity
public class CategoryEntity {

    @GraphId
    private Long id;

    @Index(unique=true)
    private String name;

    public CategoryEntity() {
    }

    public CategoryEntity(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

ogm.properties

driver=org.neo4j.ogm.drivers.bolt.driver.BoltDriver
URI=bolt://neo4j:password@localhost
connection.pool.size=150
indexes.auto=assert

travic-ci 日志中的最后几行

2017-05-28 08:58:34.316 DEBUG 7082 --- [nio-8080-exec-4] o.n.ogm.drivers.bolt.driver.BoltDriver   : No current transaction, starting a new one

2017-05-28 08:58:34.317 DEBUG 7082 --- [nio-8080-exec-4] o.n.ogm.drivers.bolt.driver.BoltDriver   : Native transaction: org.neo4j.driver.internal.ExplicitTransaction@7e0a0bb1

2017-05-28 08:58:34.317 DEBUG 7082 --- [nio-8080-exec-4] org.neo4j.ogm.session.Neo4jSession       : Thread 20: Transaction, tx id: org.neo4j.ogm.drivers.bolt.transaction.BoltTransaction@53533858

2017-05-28 08:58:34.318 DEBUG 7082 --- [nio-8080-exec-4] o.s.d.n.t.Neo4jTransactionManager        : Beginning Transaction [org.neo4j.ogm.drivers.bolt.transaction.BoltTransaction@53533858] on Session [org.neo4j.ogm.session.Neo4jSession@730479f]

2017-05-28 08:58:34.318 DEBUG 7082 --- [nio-8080-exec-4] o.s.d.n.t.Neo4jTransactionManager        : Found thread-bound Session [org.neo4j.ogm.session.Neo4jSession@730479f] for Neo4j OGM transaction

2017-05-28 08:58:34.318 DEBUG 7082 --- [nio-8080-exec-4] o.s.d.n.t.Neo4jTransactionManager        : Participating in existing transaction

2017-05-28 08:58:34.319 DEBUG 7082 --- [nio-8080-exec-4] org.neo4j.ogm.context.EntityGraphMapper  : context initialised with 0 relationships

2017-05-28 08:58:34.319 DEBUG 7082 --- [nio-8080-exec-4] org.neo4j.ogm.context.EntityGraphMapper  : visiting: se.andolf.entities.CategoryEntity@7a132ac9

2017-05-28 08:58:34.319 DEBUG 7082 --- [nio-8080-exec-4] org.neo4j.ogm.context.EntityGraphMapper  : se.andolf.entities.CategoryEntity@7a132ac9 has changed

2017-05-28 08:58:34.319 DEBUG 7082 --- [nio-8080-exec-4] org.neo4j.ogm.context.EntityGraphMapper  : mapping references declared by: se.andolf.entities.CategoryEntity@7a132ac9 

2017-05-28 08:58:34.320  INFO 7082 --- [nio-8080-exec-4] o.n.o.drivers.bolt.request.BoltRequest   : Request: UNWIND {rows} as row CREATE (n:`CategoryEntity`) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type with params {rows=[{nodeRef=-2048076489, type=node, props={name=Arms}}]}



No output has been received in the last 10m0s, this potentially indicates a stalled build or something wrong with the build itself.
Check the details on how to adjust your build configuration on: https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received

The build has been terminated

完整的日志可以在这里找到: Travis-ci build log

CategoriesControllerIT.class

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = DEFINED_PORT)
public class CategoriesControllerIT {

    @Test
    public void shouldReturn409ConflictIfCategoryNameExists(){

        final Category category = new Category("Arms");
        final String id = put(category);

        given()
                .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
                .body(category)
            .when()
                .put("/categories")
            .then()
                .statusCode(HttpStatus.CONFLICT.value());

        deleteCategory(id);
    }

    @Test
    public void shouldSaveCategory(){

        final Category category = new Category("Arms");

        final String header = given()
                .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
                .body(category)
            .when()
                .put("/categories")
            .then()
            .assertThat()
                .statusCode(201)
                .header("Location", is(notNullValue()))
                .extract().response().getHeader("Location");

        deleteCategory(UriUtil.extractLastPath(header));
    }

    private String put(Category category) {
        try {
            final String header = given().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE).body(category).put("/categories").getHeader("Location");
            return UriUtil.extractLastPath(header);
        } catch (Exception e) {
        throw new AssertionError(e);
        }
    }
}

命令 运行 neo4j 作为 IT 测试的 docker

docker run -d --name neo4j --publish=7474:7474 --publish=7687:7687 --env=NEO4J_AUTH=neo4j/password neo4j:3.2

这只是完整代码库的摘录,我粘贴了我认为相关的内容。完整代码可以在这里找到:

Lift-app

在获得有关 neo4j-user slack 的帮助后,问题是驱动程序在事务关闭时关闭会话时遇到问题。

这在 neo4j-ogm 的螺栓驱动器版本 2.1.3 中得到修复。

因此将 ogm 版本从 2.1.2 升级到 2.1.3 解决了这个问题。

相关问题:Make rollback close bolt session when transaction is closed

java-驱动程序的相关问题:java-driver version 1.3.1