Announcement Announcement Module
Collapse
No announcement yet.
Spring transactions problem: Rollback fails Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring transactions problem: Rollback fails

    Hi! I've search for problems like this in this forum and I've found some similar problems, but not the same, so, I'll be very grateful if someone could help me:

    I'm using these technologies:

    -Hibernate 3.1.
    -Spring framework 2.0.
    -jtds 1.2
    -Microsoft SQL Server 2005 Express Edition.

    The problem is that the transactional environment fails, because when I raise an Exception in a method in a facade, the rollback isn't done, and I think that my configuration is ok, here is the Spring configuration:

    <bean id="factory" class="org.springframework.orm.hibernate3.LocalSes sionFactoryBean">
    <property name="mappingResources">
    <list>
    <value>gz/cyberbrain/cyberhotel/model/room/to/roomTo.hbm.xml</value>
    ...
    </list>
    </property>
    <property name="hibernateProperties">
    <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.SQLS erverDialect</prop>
    <prop key="hibernate.show_sql">true</prop>
    </props>
    </property>
    <property name="dataSource">
    <ref bean="dataSource"/>
    </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.Hibernat eTransactionManager">
    <property name="sessionFactory">
    <ref local="factory"/>
    </property>
    </bean>

    <bean id="reservationFacadeDelegate" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager">
    <ref bean="transactionManager"/>
    </property>
    <property name="target">
    <ref local="reservationTarget"/>
    </property>
    <property name="transactionAttributes">
    <props>
    <prop key="show*">readOnly</prop>
    <prop key="find*">readOnly</prop>
    <prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_DEFAU LT</prop>
    <prop key="update*">PROPAGATION_REQUIRED, -gz.cyberbrain.cyberhotel.model.reservationfacade.e xceptions.UnavailableRoomException, ISOLATION_DEFAULT</prop>
    </props>
    </property>
    </bean>

    And here is the code that manages the update sentence and the proxy is called:

    The facade factory:

    public class SpringFacadeFactory {

    private static ApplicationContext context;

    static {
    context = new ClassPathXmlApplicationContext("applicationContext .xml");
    }

    private SpringFacadeFactory(){}

    public static ReservationFacadeDelegate getReservationFacadeDelegate() {
    return (ReservationFacadeDelegate) context.getBean("reservationFacadeDelegate");
    }

    }

    The update method in the facade:

    public void updateAReservation(ReservationTo reservationTo, Collection requestsTo) throws UnavailableRoomException {

    UpdateAReservationAction action = new UpdateAReservationAction(reservationTo, requestsTo);
    action.execute();

    }

    public class UpdateAReservationAction {

    ...

    public void execute() throws UnavailableRoomException {

    reservationDao.update(reservationTo);

    iter = oldRequests.iterator();

    for (int i=0; iter.hasNext();i++) {
    RequestTo currentRequest = (RequestTo) iter.next();
    requestDao.remove(currentRequest);
    }

    reservationDao.findRequests(reservationTo.getReser vationId());

    Collection availableRooms = roomDao.freeBetweenDates(dates);

    iter = requestsTo.iterator();

    for (int i=0; iter.hasNext();i++) {
    String currentRoomCode = ((RequestTo) iter.next()).getRoom();
    if (!availableRooms.contains(currentRoomCode)) throw new UnavailableRoomException(currentRoomCode);

    }

    RequestTo currentRequest;

    iter = requestsTo.iterator();

    for (int i=0; iter.hasNext();i++) {
    currentRequest = ((RequestTo) iter.next());
    currentRequest.setReservation(reservationTo.getRes ervationId());
    requestDao.create(currentRequest);
    }

    }

    }


    The problem is that the remove operation is not rolled back when the exception is thrown, so I think the transactional environment is not working, because when I use show_sql="true" I can't see the begin or end of a transaction:

    [java] Hibernate: update reserva set nomeReservador=?, cifReservador=?, contaReservador=?, tarxetaReservador=?, tlf=?, estadoReserva=?, dataEntrada=?, dataSaidaPrevista=?, dataSaidaReal=?, pagador=?, axencia=?, empresa=?, notas=?, porHoras=? where idReserva=?
    [java] Hibernate: delete from solicitude where reserva=? and particular=? and habitacion=? and rexime=? and tipoTarifa=?


    Does someone knows the reason? Can it be a bug for using SQL Server?
    I hope someone help me because it makes me crazy. Thanks a lot.

  • #2
    Some questions:

    - Where does UpdateAReservationAction get its reservationDao from?
    - What is reservationDao?
    - Where is the reservationFacadeDelegate bean actually used?

    And: please use [ code ] [ /code ] tags (without the blanks) around configuration, code and stacktrace snippets to improve readability.

    Regards,
    Andreas

    Comment


    • #3
      Re: Some questions

      - Where does UpdateAReservationAction get its reservationDao from?

      Code:
      It gets the Dao from: 
      
      ReservationDao reservationDao = SpringDaoFactory.getReservationDao();
      
      Where SpringDaoFactory is:
      
      public class SpringDaoFactory {
      
      	private static ApplicationContext context;
      	
      	static {
      		context = new ClassPathXmlApplicationContext("applicationContext.xml");
      		}
      	
      	private SpringDaoFactory(){}
      	
      	public static DataSource getDataSource() {
      	return (DataSource) context.getBean("dataSource");
      	}
      	
      	public static AddressDao getReservationDao() {
      		return (AddressDao) context.getBean("reservationDao");
      	}
      
      }
      
      It cames from Spring configuration:
      
      	<bean id="reservationDao" class="gz.cyberbrain.cyberhotel.model.reservation.dao.ReservationSpringDao">
      		<property name="sessionFactory">
      			<ref bean="factory"/>
      		</property>
      	</bean>
      
      - What is reservationDao?

      It's the Data Access Object that manages the persistence of reservations.

      - Where is the reservationFacadeDelegate bean actually used?

      Code:
      It is used in the controller, I only call the updateReservation method and catch the exception:
      
      try {
      
      			if (inputTesting(map))
      
      				ReservationController.updateReservation((Long) map.get("id"), (String) map.get("reservatorName"), (String) map.get("reservatorCif"), (String) map.get("reservatorAccount"), 
      						(String) map.get("reservatorCard"), (String) map.get("reservatorPhone"), (String) map.get("reservationStatus"), (Calendar) map.get("incomingDate"), 
      						(Calendar) map.get("expectedOutgoingDate"), (Calendar) map.get("trueOutgoingDate"), (Long) map.get("payer"), (Long) map.get("agency"), (Long) map.get("company"), 
      						(String) map.get("notes"), ((Boolean) map.get("byHours")).booleanValue(), vector);
      			} catch (UnavailableRoomException e) {}
      But I think that's not the problem, I use the next DataSource:

      Code:
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      		<property name="driverClassName">
      			<value>net.sourceforge.jtds.jdbc.Driver</value>
      		</property>
      		
      		<property name="url">
      			<value>jdbc:jtds:sqlserver://localhost:4492/hotel</value>
      		</property>
      		
      		<property name="username">
      			<value></value>
      		</property>
      		
      		<property name="password">
      			<value></value>
      		</property>
      	
      	</bean>
      Now I've tried using the next property of the data source:

      Code:
      <property name="defaultAutoCommit" value="false"/>
      But then commits aren't done, so nothing happens. No commits, no rollbacks.

      Comment


      • #4
        Something seems to be wrong with the application of the transaction boundaries. Though, I must confess I am a bit confused by the structure of your application.

        Is there a reason why you do not wire the datasource to the DAO and the DAO to the service within the application context?
        That way I would suggest you invoke a method on the (transactionally proxied) service from within your action and be done. It might be advisable to have a look at the Spring samples and reference manual to get an impression on how it might look like.

        And usually it is not necessary to use static accessors everywhere to access the application context. Spring really shines when it does not appear in your code ;-)

        Regards,
        Andreas

        Comment


        • #5
          Re: Confusion

          Dear Andreas, thank you for your responses and your attention.

          The structure of my application is a classic MVC structure:

          -Transfer Objects.
          -Data Access Objects.
          -Facades accesing DAO's.

          It is designed like it is recomended in the book "Hibernate Quickly" from "Manning Publications" where they use the static accesor for the SpringDaoFactory.

          Iīm sorry because English is not my native language, so I don't understand what your question means:

          Is there a reason why you do not wire the datasource to the DAO and the DAO to the service within the application context?

          Wire the datasource to the DAO! How can I do this?

          But the problem is not in the structure of my code, the problem becomes from Spring configuration, so whith the BasicDataSource and the defaultAutoCommit set to true spring always committs and with that flag set to false Spring never committs.

          Iīm sorry because I donīt understand this:

          That way I would suggest you invoke a method on the (transactionally proxied) service from within your action and be done. It might be advisable to have a look at the Spring samples and reference manual to get an impression on how it might look like.

          Thatīs I do:

          -I call the Facade method updateAReservation that is proxied, this calls the UpdateAReservationAction execute method (only for reduce code) and this calls the DAO's update and remove methods, thatīs is how it is done in MVC wellstructured applications.

          Iīve read a lot of spring documentation and books and I donīt understand whatīs wrong.

          Thank you a lot, if I find the solution I will tell it to you.

          Comment


          • #6
            Something seems to be wrong with the application of the transaction boundaries. Though, I must confess I am a bit confused by the structure of your application.
            Im confused too. Mainly due to the (imho unneccesary use of static accessors ant the like, it adds an extra not needed layer).

            I see how the DAO is retrieved, but how is the facade accessed? That is a part that I seem to be missing (why not simply inject it instead of using static accessors?!).

            Comment


            • #7
              Originally posted by infdfn00 View Post
              It is designed like it is recomended in the book "Hibernate Quickly" from "Manning Publications" where they use the static accesor for the SpringDaoFactory.
              I have not read that book so I cannot comment on it, but actually I do not like this approach.

              Originally posted by infdfn00 View Post
              Wire the datasource to the DAO! How can I do this?
              Just as plain dependency wired by Spring.

              Originally posted by infdfn00 View Post
              the problem becomes from Spring configuration, so whith the BasicDataSource and the defaultAutoCommit set to true spring always committs and with that flag set to false Spring never committs.
              This indicates that your transactional proxy is not used and each time a new hibernate session is created on the fly. With autocommit on the changes are persisted and with autocommit off, well, they are discarded.


              Originally posted by infdfn00 View Post
              Iīm sorry because I donīt understand this:

              That way I would suggest you invoke a method on the (transactionally proxied) service from within your action and be done. It might be advisable to have a look at the Spring samples and reference manual to get an impression on how it might look like.
              I meant to have a look at the sample applications shipped with Spring and have a look at the reference manual covering transaction management to see how things are solved there.

              I suggest to turn on DEBUG level logging and see if that reveals some useful information concerning your transaction.

              Regards,
              Andreas

              Comment

              Working...
              X