使用Bean-Managed Transaction,表示您要在Bean中直接以撰寫程式的方式,明確控制交易開始、送出或撤回。
實務上來說,您要在Bean上標註@TransactionManagement(TransactionManagementType.BEAN),並使用@Resource讓容器為您注入UserTransaction實例,例如:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class HelloBeanImpl implements HelloBean {
@Resource
private UserTransaction userTransaction;
....
}
      
      @TransactionManagement(TransactionManagementType.BEAN)
public class HelloBeanImpl implements HelloBean {
@Resource
private UserTransaction userTransaction;
....
}
若您要開始交易,則使用UserTransaction的begin()方法,要完成交易,則使用commit()方法,若要撤回交易,像是在例外發生時撤回交易,則使用rollback()方法,例如:
...
try {
...
userTransaction.begin();
           
// 作一些事...
      
userTransaction.commit();
} catch (Exception ex) {
try {
userTransaction.rollback();
}
catch(SystemException syex) {
Logger.getLogger(
HelloBeanImpl.class.getName()).log(Level.SEVERE, "撤回失敗", syex);
}
Logger.getLogger(
HelloBeanImpl.class.getName()).log(Level.SEVERE, "交易失敗", ex);
}
...
      
      try {
...
userTransaction.begin();
// 作一些事...
userTransaction.commit();
} catch (Exception ex) {
try {
userTransaction.rollback();
}
catch(SystemException syex) {
Logger.getLogger(
HelloBeanImpl.class.getName()).log(Level.SEVERE, "撤回失敗", syex);
}
Logger.getLogger(
HelloBeanImpl.class.getName()).log(Level.SEVERE, "交易失敗", ex);
}
...
以下是一個搭配 TimerService 與 Timer 回呼 中Message-Driven Bean的Stateless Session Bean交易範例:
- HelloBean.java
package onlyfun.caterpillar;
import javax.ejb.Local;
@Local
public interface HelloBean {
    public void demoTransaction(String message);
}- HelloBeanImpl.java
package onlyfun.caterpillar;
import java.util.logging.*;
import javax.annotation.*;
import javax.ejb.*;
import javax.jms.*;
import javax.transaction.*;
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class HelloBeanImpl implements HelloBean {
    @Resource(name = "jms/HelloQueueFactory")
    private ConnectionFactory connectionFactory;
    
    @Resource(name = "jms/HelloQueue")
    private Destination queue;
    
    @Resource
    private UserTransaction userTransaction;
    public void demoTransaction(String message) {
        Connection connection = null;
        MessageProducer producer = null;
        Session session = null;
        try {
            connection = connectionFactory.createConnection();
            session = connection.createSession(false,
                    Session.AUTO_ACKNOWLEDGE);
            
            userTransaction.begin();
            
            producer = session.createProducer(queue);
            TextMessage textMessage = session.createTextMessage();
            textMessage.setText(message + "processed....");
            producer.send(textMessage);
            userTransaction.commit();
        } catch (Exception ex) {
            try {
                userTransaction.rollback();
            }
            catch(SystemException syex) {
                Logger.getLogger(
                    HelloBeanImpl.class.getName())
                        .log(Level.SEVERE, "撤回失敗", syex);
            }
            Logger.getLogger(
                    HelloBeanImpl.class.getName())
                        .log(Level.SEVERE, "交易失敗", ex);
        }
        finally {
            try {
                producer.close();
                session.close();
                connection.close();
            } catch (JMSException ex) {
                Logger.getLogger(
                    HelloBeanImpl.class.getName())
                        .log(Level.SEVERE, "關閉失敗", ex);
            }
        }
    }
}Stateless Session Bean不保留狀態,所以交易若有某個方法中開始,則在該方法結束前要完成交易或撤回交易。
Stateful Session Bean可保留狀態,交易可以跨越多個方法呼叫,若您在Stateful Session Bean上使用BMT,若在某方法中開始交易,則您可以在該方法結束前完成交易或撤回交易,或該方法結束後不完成或撤回交易,而在下一個方法開始時,使用UserTransaction的getStatus()取得交易 狀態(Status),判斷交易與實例相關聯後繼續交易,您可以完成或撤回交易,或仍可以不完成或撤回交易,在下一個方法中再繼續完成或撤回交易。

