title: "Write operations are not allowed in read-only mode" error : confused with Spring @Service @transaction @Repository and Hibernate
body: <p>I am working on an existing project using Spring and Hibernate and am getting confused because I get a </p>
  
  <blockquote>
    <p>org.springframework.dao.InvalidDataAccessApiUsageException: Write
    operations are not allowed in read-only mode (FlushMode.MANUAL): Turn
    your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker
    from transaction definition.</p>
  </blockquote>
  
  <p>error when trying to save objects but I still can't find what exactly is wrong.</p>
  
  <p>There is a service layer that is annotated using <code>@Service</code> and a <code>save</code> method that it should be transactional so it is annotated with <code>@Transactional(readOnly = false)</code>. To me that means that spring should handle transactions itself.</p>
  
  <pre><code>@Service
  public class LadyService {
      Logger log = Logger.getLogger(LadyService.class);
      @Autowired
      private PictureDAO pictureDao;
      @Autowired
      private LadyDAO ladyDao;
      @Autowired
      private AddressDAO addressDao;
  
      @Transactional(readOnly = false)
      public void save(Lady lady) {
          Address a = addressDao.getExistingAddress(lady.getAddress());
          if (a == null) {
              a = addressDao.save(lady.getAddress());
          }
          lady.setAddress(a);
          ladyDao.save(lady);
          pictureDao.savePictures(lady.getPictures());
      }
  </code></pre>
  
  <p>The error happens when doing a save in the <code>AddressDAO</code>. It is annotated as <code>@Repository</code>.</p>
  
  <pre><code>@Repository
  public class AddressDAO extends HibernateDaoSupport {
  
      public Address save(Address address) {
          getHibernateTemplate().save(address);  &lt;-- write not permitted error happens here
          return address;
      }
  
      @SuppressWarnings({ "unchecked" })
      public Address getExistingAddress(Address address) {
          DetachedCriteria cd = DetachedCriteria.forClass(Address.class);
          cd.add(Restrictions.eqOrIsNull("administrative_area_level_1",
                  address.getAdministrative_area_level_1()));
          cd.add(Restrictions.eqOrIsNull("administrative_area_level_2",
                  address.getAdministrative_area_level_2()));
          List&lt;Address&gt; result = (List&lt;Address&gt;) getHibernateTemplate()
                  .findByCriteria(cd);
  
          if (result.isEmpty()) {
              return null;
          } else {
              return (Address) result.get(0);
          }
      }
  }
  </code></pre>
  
  <p>What I thought would happen was that <code>@Transactional</code> makes spring create a session and a transaction for the save on the service layer, and that in the DAOs, the hibernate template would get the current session and transaction that spring manages and use it to save the objects.</p>
  
  <p>The error message, though, makes me think that my service method and dao methods are not in the same transaction. </p>
  
  <p>In the servlet-context.xml there are these statements:</p>
  
  <pre><code>&lt;annotation-driven /&gt;
  
  &lt;context:component-scan base-package="com.kog.fable" /&gt;
  
  &lt;beans:bean id="mySessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt;
      &lt;beans:property name="dataSource" ref="myDataSource" /&gt;
      &lt;beans:property name="packagesToScan"&gt;
          &lt;beans:array&gt;
              &lt;beans:value&gt;com.kog.fable.**.*&lt;/beans:value&gt;
          &lt;/beans:array&gt;
      &lt;/beans:property&gt;
      &lt;beans:property name="hibernateProperties"&gt;
          &lt;beans:props&gt;
              &lt;beans:prop key="hibernate.dialect"&gt;org.hibernate.dialect.MySQLDialect
              &lt;/beans:prop&gt;
              &lt;!-- create, validate, update --&gt;
              &lt;beans:prop key="hibernate.hbm2ddl.auto"&gt;create&lt;/beans:prop&gt;
              &lt;beans:prop key="hibernate.show_sql"&gt;false&lt;/beans:prop&gt;
              &lt;beans:prop key="hibernate.connection.pool_size"&gt;10&lt;/beans:prop&gt;
              &lt;beans:prop key="hibernate.connection.autocommit "&gt;false&lt;/beans:prop&gt;
          &lt;/beans:props&gt;
      &lt;/beans:property&gt;
  &lt;/beans:bean&gt;
  
  &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
  
  &lt;beans:bean id="transactionManager"
      class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt;
      &lt;beans:property name="sessionFactory" ref="mySessionFactory" /&gt;
  &lt;/beans:bean&gt;
  
  &lt;beans:bean id="addressDAO" class="com.kog.fable.dao.AddressDAO"&gt;
      &lt;beans:property name="sessionFactory" ref="mySessionFactory" /&gt;
  &lt;/beans:bean&gt;
  
  &lt;beans:bean id="ladyDAO" class="com.kog.fable.dao.LadyDAO"&gt;
      &lt;beans:property name="sessionFactory" ref="mySessionFactory" /&gt;
  &lt;/beans:bean&gt;
  
  &lt;beans:bean id="pictureDAO" class="com.kog.fable.dao.PictureDAO"&gt;
      &lt;beans:property name="sessionFactory" ref="mySessionFactory" /&gt;
  &lt;/beans:bean&gt;
  </code></pre>
  
  <p>Here I don't understand why, if component scan is used, the DAO beans are still declared explicitly. Shouldn't the component scan feature be able to create those by itself since the DAO classes are annotated with <code>@Repository</code>?
  Since I thought this configuration could create duplicate beans, I tried deleting the xml entries, but then I started getting:</p>
  
  <blockquote>
    <p>org.springframework.beans.factory.BeanCreationException: Error
    creating bean with name 'addressController': Injection of autowired
    dependencies failed; nested exception is
    org.springframework.beans.factory.BeanCreationException: Could not
    autowire field: private com.kog.fable.dao.AddressDAO
    com.kog.fable.controller.AddressController.addressDAO; nested
    exception is org.springframework.beans.factory.BeanCreationException:
    Error creating bean with name 'addressDAO' defined in file
    [***\com\kog\fable\dao\AddressDAO.class]: Invocation of init method
    failed; nested exception is java.lang.IllegalArgumentException:
    'sessionFactory' or 'hibernateTemplate' is required</p>
  </blockquote>
  
  <p>Here I thought that the extension of HibernateDaoSupport for my DAOs would make them inherit the sessionFactory and related methods so I don't understand what happens.</p>
  
  <p>I have read that I could set the flush mode to AUTO or set the setCheckWriteOperations on the template to FALSE to solve that kind of problems and it seems to work, but I guess that this would not ensure the transaction coherence in all cases as I would like it.</p>
  
  <p>Any help would be appreciated as I am quite new to Spring and Hibernate and am a bit stuck here.</p>