2015-08-20 2 views
0

Я создаю приложение за Spring WebMVC UI с hibernate HPA. Каждый из отдельных частей головоломки прошел модульное тестирование, но у меня возникли проблемы с склеиванием приложения.Hibernate Entity Manager не может зачислить datasosurce в транзакции

Похоже, что стратегия транзакций Hibernate не позволяет Hibernate участвовать в транзакции.

Исследования до сих пор: Hibernate имеет стратегию транзакций jta, настроенную по умолчанию. Предполагается, что

Выполняется аннотация @Transactional на служебном уровне (я вижу его в журналах). Источник данных JDBC извлекается из диспетчера транзакций. Затем, в тот момент, когда диспетчер транзакций пытается подключить источник данных JDBC к транзакции, он неожиданно не может найти транзакцию. Я проследил в коде, и транзакции просто нет, когда Bitronix охотится за ней.

Стек для этой проблемы: водители

  • Postgresql XA
  • Bitronics 2.1.7
  • Hibernate 4.3.7
  • Spring 4.1.6
  • Pivotal дц Продолжительность 3.0.2 .RELEASE/8.0.15.A.RELEASE

Вот код ошибки Метод:

@Service 
public class ConfigPropertiesServiceImpl { 
    private Logger logger = LoggerFactory.getLogger(this.getClass()); 

    @Autowired 
    private ConfigPropertiesSDO configPropertiesSDO; 

    @Autowired 
    private ConfigPropertiesDAO configPropertiesDAO; 

    @Transactional 
    public PropertyValue fetchPropertyValue (String key) 
    { 
     return configPropertiesSDO.fetchProperty(key); 
    } 

} 

Лог показывает, что транзакция запускается:

DEBUG DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/myapp-war/ajax/cfgFind] 
DEBUG RequestMappingHandlerMapping - Looking up handler method for path /ajax/cfgFind 
DEBUG RequestMappingHandlerMapping - Returning handler method [public org.springframework.web.servlet.ModelAndView com.myApp.ui.security.controller.ConfigurationLayoutController.getCfgFind()] 
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'configurationLayoutController' 
DEBUG DispatcherServlet - Last-Modified value for [/myapp-war/ajax/cfgFind] is: -1 
DEBUG JtaTransactionManager - Creating new transaction with name [com.myApp.svc.config.ConfigPropertiesServiceImpl.fetchPropertyValue]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' 
DEBUG BitronixTransactionManager - beginning a new transaction 
DEBUG BitronixTransactionManager - dumping 0 transaction context(s) 
DEBUG BitronixTransaction - creating new transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002] 
DEBUG BitronixTransactionManager - creating new thread context 
DEBUG BitronixTransactionManager - changing current thread context to a ThreadContext with transaction null, default timeout 60s 
DEBUG ThreadContext - assigning <a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=NO_TRANSACTION, 0 resource(s) enlisted (started null)> to <a ThreadContext with transaction null, default timeout 60s> 
DEBUG BitronixTransaction - changing transaction status to ACTIVE 
DEBUG TransactionLogAppender - between 14848 and 14909, writing a Bitronix TransactionLogRecord with status=ACTIVE, recordLength=53, headerLength=28, time=90778990, sequenceNumber=4, crc32=-880986447, gtrid=3139322E3136382E302E35300000000005692D6D00000002, uniqueNames= 
DEBUG TransactionLogAppender - disk journal appender now at position 14909 
DEBUG BitronixTransaction - transaction status is changing from NO_TRANSACTION to ACTIVE - executing 0 listener(s) 
DEBUG TaskScheduler - scheduling transaction timeout task on a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970) for Thu Jan 01 19:13:58 CST 1970 
DEBUG TaskScheduler - removing task by a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970) 
DEBUG TaskScheduler - scheduled a TransactionTimeoutTask on a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970) scheduled for Thu Jan 01 19:13:58 CST 1970, total task(s) queued: 3 
DEBUG BitronixTransactionManager - begun new transaction at Thu Jan 01 19:12:58 CST 1970 

Log показывает, что оператор не смог присоединиться к транзакции:

DEBUG EntityManagerFactoryUtils - Opening JPA EntityManager 
TRACE SessionFactoryImpl$SessionBuilderImpl - Opening Hibernate Session. tenant=null, [email protected] 
TRACE SessionImpl - Opened session at timestamp: 14400807842 
DEBUG TransactionCoordinatorImpl - Skipping JTA sync registration due to auto join checking 
TRACE TransactionCoordinatorImpl - registered JTA platform says we cannot currently register synchronization; skipping 
DEBUG AbstractEntityManagerImpl - Looking for a JTA transaction to join 
DEBUG AbstractEntityManagerImpl - Unable to join JTA transaction 
DEBUG TransactionCoordinatorImpl - Skipping JTA sync registration due to auto join checking 

Вот моя инициализация Spring Контекст:

public class AppInitializer implements WebApplicationInitializer { 

    @Override 
    public void onStartup(ServletContext container) throws ServletException { 
     Logger logger = LoggerFactory.getLogger(this.getClass()); 


     AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
     rootContext.register(DatabaseConfig.class); 
     rootContext.refresh(); 

     // Manage the lifecycle of the root appcontext 
     container.addListener(new ContextLoaderListener(rootContext)); 
     container.setInitParameter("defaultHtmlEscape", "true"); 

     AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext(); 
     mvcContext.register(ViewConfig.class); 
     mvcContext.setServletContext(container); 

     ServletRegistration.Dynamic servlet = container.addServlet(
       "dispatcher", new DispatcherServlet(mvcContext)); 

     servlet.setLoadOnStartup(1); 
     Set<String> mappingConflicts = servlet.addMapping("/"); 

     if (!mappingConflicts.isEmpty()) { 
      for (String s : mappingConflicts) { 
       logger.error("Mapping conflict: " + s); 
      } 
      throw new IllegalStateException(
        "'appServlet' cannot be mapped to '/' under Tomcat versions <= 7.0.14"); 
     } 
    } 
} 

... и класс конфигурации базы данных, где настроено transactioning ...

@EnableTransactionManagement 
@ComponentScan({ "com.myApp.svc.*","com.myApp.core.*","com.myApp.ui.*" }) 
@Configuration 
public class DatabaseConfig { 


    @Bean(destroyMethod="shutdown") 
    public BitronixTransactionManager bitronixTransactionManager() { 
     btmConfig(); 

     return new BitronixTransactionManager(); 
    } 


    @Bean 
    public JtaTransactionManager transactionManager() { 
     JtaTransactionManager mgr = new JtaTransactionManager(); 

     mgr.setTransactionManager(bitronixTransactionManager()); 
     mgr.setUserTransaction(bitronixTransactionManager()); 

     mgr.afterPropertiesSet(); 

     return mgr; 
    } 

    @Bean 
    public TransactionTemplate transactionTemplate() 
    { 
     return new TransactionTemplate (transactionManager()); 
    } 

    @Bean(initMethod = "init", destroyMethod = "close") 
    public DataSource dataSource() { 

     PoolingDataSource dataSourceInstance = new PoolingDataSource(); 
     dataSourceInstance.set ...(); 

     dataSourceInstance.init(); 

     return dataSourceInstance; 
    } 

    @Bean 
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean() 
     throws IOException { 
    // The bean isn't created yet, but we need some of its functions 
    // This instance will be released as soon as the method goes out of 
    // scope 
    BitronixTransactionManager tm = bitronixTransactionManager(); 


    PrivateDatastoreServiceImpl pds = new PrivateDatastoreServiceImpl(); 
    pds.setPrivateDatastorePropertiesFile(privateDatastorePropertiesFile()); 
    pds.init(); 

    LocalContainerEntityManagerFactoryBean emf = null; 

    PrivateDatastoreConfigurationModel model = pds 
      .retrieveRawJdbcParameters(); 

    Properties props = new Properties(); 
    props.setProperty(HIBERNATE_DIALECT, 
      pds.getHibernateStrategy(model.getDbType())); 
    props.setProperty(HIBERNATE_DDL_AUTO, "false"); 
    props.setProperty(HIBERNATE_SHOW_SQL, "false"); 
    props.setProperty(HIBERNATE_FORMAT_SQL, "false"); 
    props.setProperty("hibernate.current_session_context_class", 
      "jta"); 
    props.setProperty("hibernate.transaction.jta.platform", 
      org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform.class.getName()); 
    props.setProperty("hibernate.jndi.class", 
      bitronix.tm.jndi.BitronixInitialContextFactory.class.getName()); 
    props.setProperty("jta.UserTransaction", 
      "BTMUserTransaction"); 

    emf = new LocalContainerEntityManagerFactoryBean(); 
    emf.setJtaDataSource(securityDataSource()); 
    emf.setJpaVendorAdapter(jpaVendorAdapter()); 
    emf.setPersistenceUnitName("myAppPersistence"); 
    emf.setPackagesToScan("com.myApp.*"); 
    emf.setJpaProperties(props); 

    return emf; 
} 


} 

Изменение: добавлены детали программного стека

ответ

0

Там были множественным взаимодействием проблем, которые все это привели в спящем режиме отказавшись присоединиться к транзакции ,

  1. Свойства спящего режима были не совсем правильными. Как написано выше, hibernate даже не пытался присоединиться к транзакции. Окончательные конфигурации Hibernate являются:

    Properties props = new Properties(); 
    props.setProperty(HIBERNATE_DIALECT, pds.getHibernateStrategy(model.getDbType())); 
    props.setProperty(HIBERNATE_DDL_AUTO, "false"); 
    props.setProperty(HIBERNATE_SHOW_SQL, "false"); 
    props.setProperty(HIBERNATE_FORMAT_SQL, "false"); 
    props.setProperty("hibernate.transaction.jta.platform", org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform.class.getName()); 
    props.setProperty("hibernate.jndi.class", bitronix.tm.jndi.BitronixInitialContextFactory.class.getName()); 
    props.setProperty("jta.UserTransaction", "BTMUserTransaction"); 
    props.setProperty("jdbc.exclusive-connection.mode", "Transactional"); 
    
    // JTA stuff 
    props.setProperty("hibernate.connection.release_mode","after_statement"); 
    props.setProperty("hibernate.current_session_context_class","jta"); 
    props.setProperty("hibernate.transaction.manager_lookup_class","org.hibernate.transaction.BTMTransactionManagerLookup"); 
    
  2. bitronix Менеджер транзакций должен быть синглтон.Insteead строительства нового менеджера транзакций, фасоль должна быть определена как:

    @Bean(destroyMethod="shutdown") 
    public BitronixTransactionManager bitronixTransactionManager() { 
        btmConfig(); 
        return TransactionManagerServices.getTransactionManager(); 
    } 
    

Наличие двух менеджеров транзакций с плавающей вокруг запутал вопрос.