使用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),判斷交易與實例相關聯後繼續交易,您可以完成或撤回交易,或仍可以不完成或撤回交易,在下一個方法中再繼續完成或撤回交易。