Results 1 to 9 of 9

Thread: How to make a non Spring Class part of a Transaction

Hybrid View

  1. #1

    Default How to make a non Spring Class part of a Transaction

    Hi,

    In my spring project, I'm using a class of "Interactive Brokers" and I explicitely annotate this class with @Component. This class is going to write into the DB via methods of a CRUDService (Spring bean), so I annotate all methods of the I.B. class with : @Transactional(propagation = Propagation.REQUIRES_NEW).

    PHP Code:
    @Component
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public class 
    RequestRealTimeBarsIB extends RetrievalBase {

        @
    Autowired
        
    private CRUDService crudService;

        @
    Transactional(propagation Propagation.REQUIRES_NEW)
        public 
    void realtimeBar(int reqIdlong timedouble opendouble highdouble lowdouble closelong volumedouble wapint count) {
              ...
              
    crudService.create(...);

    CRUDServiceBean.java


    PHP Code:
    @Repository
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    @
    Transactional(propagation Propagation.MANDATORY)
    // Above will simply ensure that a transaction has already been started when the DAO layer is entered
    public class CRUDServiceBean implements CRUDService {

        @
    PersistenceContext
        
    private EntityManager em;

        public 
    EntityManager getEntityManager() {
            return 
    em;
        }

        public <
    extends BaseEntityT create(T t) {
            
    em.persist(t);
            
    em.flush();
            
    em.refresh(t);
            return 
    t;
        } 

    The methods of RequestRealTimeBarsIB are called by Interactive brokers service automatically every 5 seconds.

    The Problem is that the create method of CRUDService is throwing an exception :
    HTML Code:
    "No Excisting transaction found for transaction marked with propagation 'mandatorry'
    How can I make sure that a transaction is started regardless how the method realtimeBar(..) is called ?

    Many thanks,

    Frank
    Last edited by fv967; Oct 11th, 2012 at 03:36 PM.

  2. #2
    Join Date
    Sep 2012
    Location
    Czech Republic
    Posts
    39

    Default

    Hi, you have several options here. If you don't have a control over creating instances of the class, you can use @Configurable annotation in combination with AspectJ weaving to register it as a Spring bean.
    If methods of the class call your Spring beans as you wrote and you want to encapsulate all the calls into a transaction, just wrap calls to the methods into a Spring bean on which you define transaction demarkation.
    If the methods don't use DB access via Spring, you can still wrap the calls into a Spring bean that creates a transaction (like in previous case) and use TransactionAwareDataSourceProxy to ensure all jdbc calls participate in the transaction.

  3. #3

    Default

    Hi,

    I've updated my question so it's better reflexing my problem. Could you please indicate what I've to do ? I'm quite new with spring.

    thanks, Frank

  4. #4
    Join Date
    Sep 2012
    Location
    Czech Republic
    Posts
    39

    Default

    From the exception string you have posted it is obvious that you have a transaction manager set up. I assume that you use <tx:annotation-driven />. Ensure that crudService.create(...) is called in the same thread as realTimeBar(...) (Spring transactions are bound to a thread). Next, make sure you have autocommit turned off on a data source. You can log debug messages on Spring JpaTransactionManager class to see if a transaction is created when realtimeBar is called (I assume you use JpaTransactionManager).

    >> The methods of RequestRealTimeBarsIB are called by Interactive brokers service automatically every 5 seconds.
    Who is reponsible for creating the instance of RequestRealTimeBarsIB? Is it injected somewhere or obtained by springContext.getBean()? It should be. In the previous version of your post I remember you wrote that the caller is not a Spring managed bean. Which one is it? (If RequestRealTimeBarsIB, how do you obtain CRUDService to it?)

    Another thing not related to the transaction problem - it is more common to use a singleton scope for beans that do not hold a state that differs among instances (at least CrudServiceBean in your case).

  5. #5

    Default

    Hi,

    Many thanks for your help !!!
    Yes, I've a transaction manager setup.
    The applicationcontext.xml

    PHP Code:
    <?xml version="1.0" encoding="UTF-8"?> 
                
    <beans xmlns="http://www.springframework.org/schema/beans" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:tx="http://www.springframework.org/schema/tx" 
           xmlns:context="http://www.springframework.org/schema/context" 
           xmlns:task="http://www.springframework.org/schema/task" 
           xsi:schemaLocation=" 
               [url]http://www.springframework.org/schema/beans[/url]  
               [url]http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/url] 
               [url]http://www.springframework.org/schema/tx[/url]  
               [url]http://www.springframework.org/schema/tx/spring-tx-3.0.xsd[/url] 
               [url]http://www.springframework.org/schema/context[/url]  
               [url]http://www.springframework.org/schema/context/spring-context-3.0.xsd[/url] 
               [url]http://www.springframework.org/schema/task[/url]  
               http://www.springframework.org/schema/task/spring-task-3.0.xsd">            
                
        <context:component-scan base-package="com.stockdomain"> 
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 
        </context:component-scan>     
         
        <bean id="contextApplicationContextProvider" class="com.stockdomain.util.ApplicationContextProvider"></bean>          

        <!-- dataSource --> 
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
          <property name="driverClassName"><value>org.postgresql.Driver</value></property> 
          <property name="url"><value>jdbc:postgresql://localhost/db_finance</value></property> 
          <property name="username"><value>xxxxx</value></property> 
          <property name="password"><value>xxxxx</value></property> 
        </bean>  
         
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
            <property name="entityManagerFactory" ref="entityManagerFactory" /> 
        </bean>   

        <bean id="entityManagerFactory" 
              class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
            <property name="persistenceUnitName" value="mypersistenceunit" /> 
            <property name="dataSource" ref="dataSource" /> 
            <property name="jpaVendorAdapter"> 
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
                    <property name="showSql" value="true" /> 
                    <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" /> 
                </bean> 
            </property> 
            <property name="jpaPropertyMap"> 
                <map> 
                    <entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> 
                </map> 
            </property> 
        </bean> 
             
        <tx:annotation-driven transaction-manager="transactionManager"/>  
         
    </beans>

    Th
    e CRUDService.create(..) should be called in the same thread as realTimeBar(..).
    I'll double check that by logging debug messages on Spring JpaTransactionManager. (I hope I'll be able to manage that :-( ).

    The autocommit is turned off on my DB.

    Who is reponsible for creating the instance of RequestRealTimeBarsIB?
    RequestRealTimeBarsIB is autowired into a Controller. This Controller is calling a method "requestRealTimeBarsIB .eConnect()" . This makes is possible for the Interactive Brokers application to call realtimeBar(...) every 5 seconds.
    When I wrote that "the caller is not a Spring managed bean" , I meant the Interactive Brokers application (running as a separate apllication) which is calling realtimeBar(...) .

    I'll change the type of CRUDServiceBean, so that it becomes a singleton.

  6. #6

    Default

    I managed to log debug messages on Spring JpaTransactionManager. But, I don't get any debug messages for when the interactive brokers application is calling realtimeBar(...).
    This means that a because the IB application runs in a separate thread, no transaction is started ?

    How can I force the creation of a transaction ?

    Thanks, Frank

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •