The test with transactionrequiredexception failed: when loading JPA and neo4j configurations, no transaction is in progress
I have a JPA web application that contains some integration tests for the JPA repository At present, there is no integration test for the neo4j repository
Now, I have added some neo4j features to this existing JPA web application
I am now using the neo4j repository and the JPA repository My entity and repository have different names and are located in different packages
My tests all extend the following classes:
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ApplicationConfiguration.class,WebSecurityTestConfiguration.class,WebConfiguration.class })
@Transactional
public abstract class AbstractControllerTest {
...
}
When the application configuration does not have any tests, the tests run normally
Neo4J configuration:
@Configuration
@ComponentScan(basePackages = { "it.robot.rest.config" })
@Import({ DatabaseConfiguration.class,Log4jWeb.class })
public class ApplicationConfiguration {
}
However, when adding the neo4j configuration, they will make an error in the exception:
@Configuration
@ComponentScan(basePackages = { "it.robot.rest.config" })
@Import({ DatabaseConfiguration.class,Neo4JRepositoryConfiguration.class,Log4jWeb.class })
public class ApplicationConfiguration {
}
The exceptions are:
javax.persistence.TransactionrequiredException: no transaction is in progress
This is the neo4j configuration (I tried the neo4jconfiguration and crossstoreneo4jconfiguration classes, and I got the same exception):
@Configuration
@EnableNeo4jRepositories(basePackages = { "it.robot.data.neo4j.repository" } )
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.neo4j.service" })
public class Neo4JRepositoryConfiguration extends Neo4jConfiguration {
public static final String URL = "http://localhost:7474/db/data/";
public static final String LOGIN = "neo4j";
public static final String PASSWORD = "mypassword";
Neo4JRepositoryConfiguration() {
setBasePackage("it.robot.data.neo4j.domain");
}
@Bean
GraphDatabaseService graphDatabaseService() {
return new SpringCypherRestGraphDatabase(URL,LOGIN,PASSWORD);
}
}
This is the JPA configuration:
@Configuration
@Import({ JpaService.class,Log4j.class })
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.config" })
@EnableJpaRepositories(basePackages = { "it.robot.data.jpa" },repositoryfactorybeanClass = it.robot.data.jpa.repository.GenericRepositoryfactorybean.class)
public class DatabaseConfiguration {
...
}
It seems that the neo4jconfiguration class transaction manager has the same name as the JPA transaction manager ("transaction manager") and overrides it
I will use the JPA transaction manager provided by spring to satisfy Neo 4J, but I wonder if it is feasible
Some additional information
I am using spring-data-neo4j and spring-data-neo4j-rest version 3.3 2.RELEASE
I am using the neo4j database instead of the embedded server. Of course, the neo4j server has been started
I disabled authentication on the database because it blocked my curl request and did not seem to update the password:
curl -H "Accept:application/json"
-H "Content-Type: application/json"
"http://localhost:7474/user/neo4j/password"
-X POST -d "{ \"password\" : \"myownpassword\" }"
The only user I know doesn't seem to have a strong voice:
stephane@stephane-ThinkPad-X301:~> curl -H "Accept:application/json" -H "Content-Type: application/json" "http://localhost:7474/user/neo4j" stephane@stephane-ThinkPad-X301:~> stephane@stephane-ThinkPad-X301:~>
I didn't create any "architecture / structure" in the diagram, and I'm not sure if I should
Neo4j entity:
@NodeEntity
@SequenceGenerator(name = "id_generator",sequenceName = "sq_id_part")
public class Neo4JPart extends BaseEntity {
@Column(nullable = false)
private String name;
@Column(nullable = false,unique = true)
private String serialNumber;
private Integer weight;
@ManyToOne
@JoinColumn(name = "manufacturer_id",nullable = false)
private Neo4JManufacturer manufacturer;
@Fetch
@RelatedTo(type = "part",direction = Direction.BOTH)
public Set<Neo4JPart> parts;
public Neo4JPart() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Neo4JManufacturer getManufacturer() {
return manufacturer;
}
public void setManufacturer(Neo4JManufacturer manufacturer) {
this.manufacturer = manufacturer;
}
public Set<Neo4JPart> getParts() {
return parts;
}
public void setParts(Set<Neo4JPart> parts) {
this.parts = parts;
}
public String toString() {
String results = name + "'s compatible parts include\n";
if (parts != null) {
for (Neo4JPart part : parts) {
results += "\t- " + part.name + "\n";
}
}
return results;
}
}
@MappedSuperclass
public class BaseEntity {
@GraphId
@GeneratedValue(strategy = GenerationType.AUTO,generator = "id_generator")
@Column(name = "id")
private Long id;
@Version
@Column(nullable = false)
private int version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getVersion() {
return this.version;
}
public void setVersion(int version) {
this.version = version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (this.id == null || obj == null || !(this.getClass().equals(obj.getClass()))) {
return false;
}
BaseEntity that = (BaseEntity) obj;
return this.id.equals(that.getId());
}
@Override
public int hashCode() {
return id == null ? 0 : id.hashCode();
}
}
And neo4j repositories:
public interface Neo4JPartRepository extends GraphRepository<Neo4JPart> {
public Neo4JPart findByName(String name);
public Neo4JPart findBySerialNumber(String serialNumber);
public Page<Neo4JPart> findByManufacturer(@Param("manufacturer") Neo4JManufacturer manufacturer,Pageable page);
public List<Neo4JPart> findByManufacturer(@Param("manufacturer") Neo4JManufacturer manufacturer);
public Page<Neo4JPart> findByPartsName(String name,Pageable page);
}
public interface Neo4JManufacturerRepository extends GraphRepository<Neo4JManufacturer> {
Neo4JManufacturer findByName(String name);
}
Maven dependencies are:
<org.springframework.version>4.1.2.RELEASE</org.springframework.version>
<hibernate.version>4.3.6.Final</hibernate.version>
<dependencies>
<dependency>
<groupId>com.thalasoft</groupId>
<artifactId>tool@R_332_2419@</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2.1</version>
</dependency>
<dependency>
<groupId>MysqL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.172</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.10.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.jodatime</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-rest</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-cross-store</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>
</dependencies>
I tried to upgrade to search maven. Org Version 0, but the build now provides the following exceptions:
AnnotationFormatError: Invalid default: public abstract java.lang.Class org.springframework.data.neo4j.config.EnableNeo4jRepositories.repositoryBaseClass()
I'm referring to the documentation http://docs.spring.io/spring-data/neo4j/docs/3.4.0.RELEASE/reference/pdf/spring-data-neo4j-reference.pdf You don't see any information about repository baseClass in
The source code Javadoc only says:
Configure the repository base class to be used to create repository proxies for this particular configuration.
This gives me a headache and wants to know what a repository agent is if I need one in my case
Solution
I can use the solution provided by the chain transaction manager in implementing spring chainedtransactionmanager according to the "best forces 1pc" pattern to solve the problem, following Simon's how do I properly set up cross store persistence using spring data JPA + neo4j? Tips for
I just need to change my neo4j configuration I don't even need to touch anything in another JPA transaction manager
This is my neo4j configuration:
@EnableNeo4jRepositories(basePackages = { "it.robot.data.neo4j.repository" })
@EnableTransactionManagement
@ComponentScan(basePackages = { "it.robot.data.neo4j.service" })
public class Neo4JRepositoryConfiguration extends Neo4jConfiguration {
private static Logger logger = LoggerFactory.getLogger(Neo4JRepositoryConfiguration.class);
public static final String URL = "http://localhost:7474/db/data/";
public static final String LOGIN = "neo4j";
public static final String PASSWORD = "xxxxx";
Neo4JRepositoryConfiguration() {
setBasePackage("it.robot.data.neo4j.domain");
}
@Bean
GraphDatabaseService graphDatabaseService() {
return new SpringCypherRestGraphDatabase(URL,PASSWORD);
}
@Autowired
LocalContainerEntityManagerfactorybean entityManagerFactory;
@Override
public PlatformTransactionManager neo4jTransactionManager(
GraphDatabaseService graphDatabaseService) {
return new ChainedTransactionManager(
new JpaTransactionManager(entityManagerFactory.getObject()),new JtaTransactionManagerfactorybean(graphDatabaseService).getObject());
}
}
