2017-04-19 7 views
1

Spring MVCアプリケーションの基盤となるJTA実装としてAtomikosを使用して、埋め込みH2 DBとActiveMQで分散トランザクションを設定しようとしています。 私は遭遇しているエラーに関連したウェブ/ stackoverflowのほとんどすべてのページに従ってきましたが、それを理解することはできませんでした。ここでAtomikosでActiveMQと埋め込みH2を含む分散トランザクションを設定できません

は、コンフィギュレーションの関連する部分です:

@Autowired 
    @Bean(name = "transactionManager") 
    public PlatformTransactionManager getJtaTransactionManager(TransactionManager usrTxMgr, 
                  @Qualifier("AtomikosUserTransaction") UserTransaction usrTx) { 
    return new JtaTransactionManager(usrTx, usrTxMgr); 
} 

@Autowired 
@Bean(name = "transactionManager") 
public PlatformTransactionManager getJtaTransactionManager(TransactionManager usrTxMgr, 
                  @Qualifier("AtomikosUserTransaction") UserTransaction usrTx) { 
    return new JtaTransactionManager(usrTx, usrTxMgr); 
} 

@Bean(name = "AtomikosTransactionManager", initMethod = "init", destroyMethod = "close") 
public TransactionManager getAtomikosTransactionManager() { 
    return new UserTransactionManager(); 
} 

@Bean(name = "AtomikosUserTransaction") 
public UserTransaction getAtomikosUserTransaction() throws SystemException { 
    UserTransactionImp usrTx = new UserTransactionImp(); 
    usrTx.setTransactionTimeout(30); 
    return usrTx; 
} 

@Bean(name = "H2X") 
public AtomikosDataSourceBean getXADataSource() { 
    JdbcDataSource h2x = new JdbcDataSource(); 
    h2x.setURL("jdbc:h2:˜/test1" + ";" + "INIT=RUNSCRIPT FROM 'classpath:sql/create-db.sql'"); 
    h2x.setUser("sa"); 
    h2x.setPassword(""); 

    AtomikosDataSourceBean atkDs = new AtomikosDataSourceBean(); 
    atkDs.setXaDataSource(h2x); 
    atkDs.setUniqueResourceName("AtomikosXADataSource"); 
    return atkDs; 
} 


@Autowired 
@Bean(name = "H2TemplateX") 
public NamedParameterJdbcTemplate getJdbcTemplateX(@Qualifier("H2X") AtomikosDataSourceBean atkDs) { 
    return new NamedParameterJdbcTemplate(atkDs); 
} 

@Bean(name = "ActiveMQXACF") 
public ConnectionFactory getXAConnectionFactory(@Value("${brokerURL:tcp://localhost:61616}") String brokerURL) { 
    ActiveMQXAConnectionFactory activeMQXAConnectionFactory = new org.apache.activemq.ActiveMQXAConnectionFactory(brokerURL); 
    AtomikosConnectionFactoryBean atomikosJMSConnectionFactoryBean = new AtomikosConnectionFactoryBean(); 
    atomikosJMSConnectionFactoryBean.setUniqueResourceName("AtomikosJMSConnectionFactory"); 
    atomikosJMSConnectionFactoryBean.setXaConnectionFactory(activeMQXAConnectionFactory); 

    return atomikosJMSConnectionFactoryBean; 
} 

@Bean(name = "JMSTemplateX") 
public JmsTemplate getXAJMSTemplate(@Autowired @Qualifier("ActiveMQXACF") ConnectionFactory cf, @Value("${JMSDestination}") String destination) { 
    JmsTemplate jt = new JmsTemplate(); 
    jt.setConnectionFactory(cf); 
    jt.setDefaultDestinationName(destination); 
    jt.setSessionTransacted(true); 
    return jt; 
} 

これらは@Transactionalを注釈を付けている方法です。それらはすべて異なるサービス/リポジトリ/コンポーネントクラスにあります。デバッグ中に春の取引を置く

@Transactional 
public void saveMessage(String message) { 
    messageSaver.insertMessage(message); 
    processor.processMessage(message); 
} 

@Transactional 
public void processMessage(final String message){ 
    jmsTemplate.send("Queue1", new MessageCreator() { 
     public Message createMessage(Session session) throws JMSException { 
      return session.createTextMessage(message); 
     } 
    }); 
} 

@Transactional 
public void insertMessage(String msg) { 
    if (msg.toLowerCase().contains("bad")) throw new RuntimeException("Can't Commit to DB !!"); 
    Map<String, Object> params = new HashMap<String, Object>(); 
    params.put("msg", msg); 
    String sql = "insert into TBL_MESSAGE (message) values(:msg)"; 
    jdbcTemplateX.update(sql, params); 
} 

、私は春が正しくトランザクションメソッドとAtomikos UserTransactionManagerとUserTransactionImpクラスを登録していることがわかります。 短縮ログ:

Adding transactional method 'business.MessageDaoImpl.insertMessage 
    Adding transactional method 'business.OrderProcessor.processMessag 
    Adding transactional method 'business.MessageServiceService.saveMe 
    org.springframework.transaction.jta.JtaTransactionManager - Using JTA UserTransaction: [email protected] 
    org.springframework.transaction.jta.JtaTransactionManager - Using JTA TransactionManager: [email protected] 

これらはAtomikosデバッグログからいくつかのログです:メッセージを送信すると、メッセージの送信がI JTAトランザクションのコンテキストで実行されるべきであると述べていながら

DEBUG http-nio-8080-exec-1 com.atomikos.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'AtomikosXADataSource': getConnection()... 
    INFO http-nio-8080-exec-1 com.atomikos.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'AtomikosXADataSource': init... 
    WARN http-nio-8080-exec-1 com.atomikos.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'AtomikosXADataSource': poolSize equals default - this may cause performance problems! 
    INFO http-nio-8080-exec-1 com.atomikos.jdbc.AtomikosDataSourceBean - AtomikosDataSoureBean 'AtomikosXADataSource': initializing with [ xaDataSourceClassName=null, uniqueResourceName=AtomikosXADataSource, maxPoolSize=1, minPoolSize=1, borrowConnectionTimeout=30, maxIdleTime=60, reapTimeout=0, maintenanceInterval=60, testQuery=null, xaProperties=[], loginTimeout=0, maxLifetime=0] 
    INFO http-nio-8080-exec-1 com.atomikos.datasource.xa.XATransactionalResource - AtomikosXADataSource: refreshed XAResource 
    DEBUG http-nio-8080-exec-1 com.atomikos.jdbc.AtomikosConnectionProxy - atomikos connection proxy for conn5: url=jdbc:h2:˜/test1 user=SA: calling prepareStatement(insert into TBL_MESSAGE (message) values(?))... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jdbc.AtomikosConnectionProxy - atomikos connection proxy for conn5: url=jdbc:h2:˜/test1 user=SA: close()... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosConnectionFactoryBean - AtomikosConnectionFactoryBean 'AtomikosJMSConnectionFactory': createConnection()... 
    INFO http-nio-8080-exec-1 com.atomikos.jms.AtomikosConnectionFactoryBean - AtomikosConnectionFactoryBean 'AtomikosJMSConnectionFactory': init... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosConnectionFactoryBean - AtomikosConnectionFactoryBean 'AtomikosJMSConnectionFactory': getReference()... 
    INFO http-nio-8080-exec-1 com.atomikos.jms.AtomikosConnectionFactoryBean - AtomikosConnectionFactoryBean 'AtomikosJMSConnectionFactory': initializing with [ xaCo[email protected]59883d41, xaConnectionFactoryClassName=null, uniqueResourceName=AtomikosJMSConnectionFactory, maxPoolSize=1, minPoolSize=1, borrowConnectionTimeout=30, maxIdleTime=60, reapTimeout=0, maintenanceInterval=60, xaProperties=[], localTransactionMode=false, maxLifetime=0, ignoreSessionTransactedFlag=true] 
    INFO http-nio-8080-exec-1 com.atomikos.datasource.xa.XATransactionalResource - AtomikosJMSConnectionFactory: refreshed XAResource 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsConnectionProxy - atomikos connection proxy for resource AtomikosJMSConnectionFactory: creating XA-capable session... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa session proxy for resource AtomikosJMSConnectionFactory: calling toString on JMS driver session... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa session proxy for resource AtomikosJMSConnectionFactory: calling createQueue on JMS driver session... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa session proxy for resource AtomikosJMSConnectionFactory: calling createProducer on JMS driver session ActiveMQSession {id=ID:IG11061-58249-1492635876500-5:2:2,started=false} 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa session proxy for resource AtomikosJMSConnectionFactory: calling createTextMessage on JMS driver session... 
    DEBUG http-nio-8080-exec-1 com.atomikos.jms.AtomikosJmsMessageProducerProxy - atomikos MessageProducer proxy for ActiveMQMessageProducer { value=ID:IG11061-58249-1492635876500-5:2:2:1 }: send (message)... 
    WARN http-nio-8080-exec-1 com.atomikos.jms.ConsumerProducerSupport - atomikos MessageProducer proxy for ActiveMQMessageProducer { value=ID:IG11061-58249-1492635876500-5:2:2:1 }: The JMS session you are using requires a JTA transaction context for the calling thread and none was found. 

エラー@Transactionalアノテーションが存在するため、最初のメソッド呼び出しで作成されると仮定していました。

私はエラーを生成Atomikosクラスのソースを見たがmuch.Theエラーが参加して起こる()メソッドを見つけ出すことができませんでした:

protected void enlist() throws JMSException { 
    CompositeTransaction ct = null; 
    CompositeTransactionManager ctm = this.getCompositeTransactionManager(); 
    boolean enlist = false; 
    if(ctm != null) { 
     ct = ctm.getCompositeTransaction(); 
     if(ct != null && ct.getProperty("com.atomikos.icatch.jta.transaction") != null) { 
      enlist = true; 
     } 
    } 

    if(enlist) { 
     this.registerSynchronization(ct); 

     try { 
      this.state.notifyBeforeUse(ct); 
     } catch (InvalidSessionHandleStateException var6) { 
      String msg1 = "error during enlist: " + var6.getMessage(); 
      LOGGER.logWarning(this + ": " + msg1); 
      AtomikosJMSException.throwAtomikosJMSException(msg1, var6); 
     } 
    } else { 
     String msg = "The JMS session you are using requires a JTA transaction context for the calling thread and none was found.\nPlease correct your code to do one of the following: \n1. start a JTA transaction if you want your JMS operations to be subject to JTA commit/rollback, or\n2. increase the maxPoolSize of the AtomikosConnectionFactoryBean to avoid transaction timeout while waiting for a connection, or\n3. create a non-transacted session and do session acknowledgment yourself, or\n4. set localTransactionMode to true so connection-level commit/rollback are enabled."; 
     LOGGER.logWarning(this + ": " + msg); 
     AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException(msg); 
    } 

任意の助けをいただければ幸いに!!

答えて

1

このリンクは助けた:引用 http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/

: を「これはあなたが@Autowired Beanまたは取引を通じて直接あなたの注釈付きメソッドを呼び出す必要があることを意味は、起動することはありませんあなたは@Autowired上のメソッドを呼び出した場合。 Beanはアノテートされていないアノテートされたパブリックメソッドを呼び出します。あなたのアノテーションは無視されます。これは、AOPが@Autowiredコードを最初に入力したときにのみアノテーションをチェックするからです。

WebConfigクラスに@EnableTransactionMangementを入れても機能しました。 @EnableTransactionManagementアノテーションは、自分のRootConfigクラスのいずれかでのみ使用できました。@ Serviceメソッドと2つの後続の@Repositoryメソッドで、 @Transactionalと共に使用できます。

Spring Transaction Boundariesがどのように設定され、さまざまな@ Enable *注釈が内部的にどのように機能するかについて、もっと読むべきでしょう。

まだ明確ではありませんが、現在は機能しています。

他人にも役立つことを願っています。

関連する問題