title: Spring Data Neo4j - Exception when trying to use @Transactional annotation
body: <p>I'm quite new with Spring Data and Neo4j, and there is something i don't understand about using the @Transactional annotation. It seems that i must declare an empty constructor for a class which i annotated one of its methods with @Transactional, and I also need to create an empty constructor for the node entities classes that the transaction will use... (and if i don't declare the empty constructors, i get an exception). But.. maybe i'm missing something. I'll show you an example, below is a code for example, which demonstrates what i'm talking about (Its a short spring-data-neo4j setup that gets things up and running):</p>
  
  <p>My configuration class:</p>
  
  <pre><code>@Configuration
  @ComponentScan(basePackages={"org.technion.socialrescue.core"})
  @ImportResource("spring-data-context.xml")
  @EnableTransactionManagement
  public class DefaultApplicationConfig {
      @Bean(destroyMethod = "shutdown")
      public GraphDatabaseService graphDatabaseService() {
          return new EmbeddedGraphDatabase("target/graph.db");
      }
  }
  </code></pre>
  
  <p>the spring-data-context.xml file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         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/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd"&gt;
  
  
      &lt;neo4j:config graphDatabaseService="graphDatabaseService" /&gt;
      &lt;neo4j:repositories base-package="org.technion.socialrescue" /&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>The class that hosts the method that is marked with @Transactional:</p>
  
  <pre><code>@Component("someClass")
  public class SomeClass {
  
      public SomeObjectRepository someObjects;    
  
      @Autowired
      public SomeClass(SomeObjectRepository someOBjects) {
          this.someObjects = someOBjects;
      }
  
      @Transactional
      public void someMethod() {
          someObjects.save(new SomeObject("roy"));        
      }
  }
  </code></pre>
  
  <p>the SomeObject class (which will be used as a node in the graph):</p>
  
  <pre><code>@NodeEntity
  public class SomeObject {
  
      public SomeObject(String name) {
          this.name = name;
      }
  
      @GraphId
      private Long id;    
  
      @Indexed
      String name;
  }
  </code></pre>
  
  <p>The SomeObjectRepository interface:</p>
  
  <pre><code>package org.technion.socialrescue.core;
  
  import org.springframework.data.neo4j.repository.GraphRepository;
  
  public interface SomeObjectRepository extends GraphRepository&lt;SomeObject&gt; {
  
  }
  </code></pre>
  
  <p>and the code that launch the application:</p>
  
  <pre><code>public class Playground {
  
      public static void main(String[] args) {
          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DefaultApplicationConfig.class);
          SomeClass someClass = (SomeClass)context.getBean("someClass");
          someClass.someMethod();
          context.close();
      }
  }
  </code></pre>
  
  <p>So, by running the code above, I'm getting the following exception:</p>
  
  <pre><code>Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someClass' defined in file [C:\Users\t-rvelic\workspace\social-rescue\target\classes\org\technion\socialrescue\core\SomeClass.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.technion.socialrescue.core.SomeClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
      at org.springframework.context.annotation.AnnotationConfigApplicationContext.&lt;init&gt;(AnnotationConfigApplicationContext.java:73)
      at org.technion.socialrescue.playground.Playground.main(Playground.java:13)
  Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.technion.socialrescue.core.SomeClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
      at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:217)
      at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
      at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
      ... 10 more
  Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
      at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
      at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
      at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
      at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
      at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
      at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
      at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
      at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
      ... 17 more
  </code></pre>
  
  <p>So i tried to follow the cause for this exception, and added an empty constructor for <code>SomeClass</code>, so it looks like this:</p>
  
  <pre><code>@Component("someClass")
  public class SomeClass {
  
      public SomeObjectRepository someObjects;
  
      public SomeClass() {
  
      }   
  
      @Autowired
      public SomeClass(SomeObjectRepository someOBjects) {
          this.someObjects = someOBjects;
      }
  
      @Transactional
      public void someMethod() {
          someObjects.save(new SomeObject("roy"));        
      }
  }
  </code></pre>
  
  <p>Then, i launched again my app, and got the following exception:</p>
  
  <pre><code>Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: SomeObject: entity must have a no-arg constructor.; nested exception is java.lang.IllegalArgumentException: SomeObject: entity must have a no-arg constructor.
      at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:43)
      at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
      at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
      at com.sun.proxy.$Proxy39.save(Unknown Source)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
      at com.sun.proxy.$Proxy40.save(Unknown Source)
      at org.technion.socialrescue.core.SomeClass.someMethod(SomeClass.java:23)
      at org.technion.socialrescue.core.SomeClass$$FastClassByCGLIB$$d9c3b9ef.invoke(&lt;generated&gt;)
      at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
      at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
      at org.technion.socialrescue.core.SomeClass$$EnhancerByCGLIB$$d5a7b8cd.someMethod(&lt;generated&gt;)
      at org.technion.socialrescue.playground.Playground.main(Playground.java:17)
  Caused by: java.lang.IllegalArgumentException: SomeObject: entity must have a no-arg constructor.
      at org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator$1.create(AbstractConstructorEntityInstantiator.java:87)
      at org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator.createEntityFromState(AbstractConstructorEntityInstantiator.java:56)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedInstantiator.createEntityFromState(Neo4jEntityPersister.java:135)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedInstantiator.createEntityFromState(Neo4jEntityPersister.java:122)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:86)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:170)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:189)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:244)
      at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231)
      at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:293)
      at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:287)
      at org.springframework.data.neo4j.repository.AbstractGraphRepository.save(AbstractGraphRepository.java:109)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
      ... 28 more
  </code></pre>
  
  <p>So this time, i added an empty constructor for the <code>SomeObject</code> class, it looks like that:</p>
  
  <pre><code>@NodeEntity
  public class SomeObject {
  
      public SomeObject() {
  
      }
  
      public SomeObject(String name) {
          this.name = name;
      }
  
      @GraphId
      private Long id;    
  
      @Indexed
      String name;
  }
  </code></pre>
  
  <p>And then it worked... </p>
  
  <p>But why it worked? why i had to add two empty constructors? I tried to google it, found nothing. I really want to know why it behaves like that... any help will be highly appreciated!</p>
  
  <p>Thanks!</p>