简体   繁体   中英

Migrating from embedded neo4j to REST using Spring Data

I've been developing my project using neo4j embedded and SpringData. Everything works well and has been thoroughly tested with the embedded database. I was under the impression ( http://docs.spring.io/spring-data/data-graph/docs/1.1.0.RC1/reference/multi/reference_neo4j-server.html ) that moving to the REST API was going to be a simple change to the Application Context (see the link above). However, when I try to use the REST api, I'm getting a java IllegalStateException with the message "Not In Transaction". I do not see this error using the embedded database.

I'm using the @Transactional annotation successfully with the embedded DB. The only code change is to the "graphDatabaseService" bean in the application context as indicated in the link above.

How does one typically work around this error? I have to think that it is commonly hit. Please find below a very simple repro of the issue.

This returns

Exception

org.springframework.transaction.TransactionSystemException: Unexpected internal transaction state; nested exception is java.lang.IllegalStateException: Not in transaction

NeoTest.java

package com.mycompany.hellospringdata;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.*;

@ContextConfiguration(locations = "classpath:testContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class NeoTest {

  @Autowired
  Neo4jTemplate template;

  @Test
  @Transactional
  public void testSomething() {

    Person add = new Person();
    add.setName("Jorgan Jorgansen");
    add = template.save(add); 

    Person other = template.findOne(add.getId(), Person.class);
    assertNotNull("Retrieved entity is non-null", other);
    assertEquals("Retrieved entity equals saved entity", add, other);

  }
}

Person.java

package com.mycompany.hellospringdata;

import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.NodeEntity;

@NodeEntity
public class Person {
  @GraphId
  private Long id;

  private String name;

  public String getName() {
    return name;
  }

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

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  @Override
  public int hashCode() {
    int hash = 7;
    hash = 23 * hash + (this.name != null ? this.name.hashCode() : 0);
    return hash;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final Person other = (Person) obj;
    if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
      return false;
    }
    return true;
  }

}

testContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/data/neo4j
            http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd">

    <context:annotation-config/>
    <neo4j:config graphDatabaseService="graphDatabaseService"/>

    <!-- 
    <bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
     -->


    <bean id="graphDatabaseService" class="org.neo4j.rest.graphdb.RestGraphDatabase">
            <constructor-arg value="http://<neo4j-server-here>:7474/db/data"/>
    </bean>

</beans>

pom.xml

<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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId> 
  <artifactId>helloSpringData</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>helloSpringData</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <repositories>
      <repository>
          <id>neotechnology-releases</id>
          <url>http://m2.neo4j.org/content/repositories/releases/</url>
      </repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>org.neo4j</groupId>
      <artifactId>neo4j</artifactId>
      <version>1.9.3</version>
    </dependency>
    <dependency>
         <groupId>org.neo4j</groupId>
         <artifactId>neo4j-kernel</artifactId>
         <version>1.9.3</version>
    </dependency> 
    <dependency>
       <groupId>org.neo4j</groupId>
       <artifactId>neo4j-kernel</artifactId>
       <version>1.9.3</version>
       <type>test-jar</type>
       <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-cypher</artifactId>
        <version>1.9.3</version>
    </dependency>
    <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-rest-graphdb</artifactId>
        <version>1.9</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rest</artifactId>
        <version>2.2.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-neo4j</artifactId>
      <version>2.2.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>3.2.3.RELEASE</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <version>1.6.6</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-simple</artifactId>
         <version>1.6.6</version>
     </dependency>
     <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.0</version>
    </dependency>
   <dependency>
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm-all</artifactId>
        <version>4.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-validation_1.0_spec</artifactId>
        <version>1.1</version>
    </dependency>

  </dependencies>
</project>

Well, after a few painful hours, here's what got it to work.

  1. Update the POM to use the latest version of SpringData

  2. Remove @Transactional. It isn't supported for REST yet.

Here's the updated POM

    <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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId> 
  <artifactId>helloSpringData</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>helloSpringData</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rest</artifactId>
        <version>2.3.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>2.3.1.RELEASE</version>
    </dependency>        
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>3.2.3.RELEASE</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
       <version>1.6.6</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-simple</artifactId>
         <version>1.6.6</version>
     </dependency>
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-validation_1.0_spec</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.0</version>
    </dependency>  
    <dependency>
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm-all</artifactId>
        <version>4.1</version>
    </dependency>
  </dependencies>
</project>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM