У меня есть требование попытаться добиться распространения транзакций по нескольким фазам с состоянием. У меня есть 3 Stateful EJB; s в моем приложении. Управление запуском и завершением контролируется внешним приложением Java через вызов метода удаленного интерфейса.EJB: Достижение распространения транзакций через управляемую Bean транзакцию?
@Remote
@Stateful
public class MyEJB1 implements RemoteEJB1{
@EJB
private RemoteEJB2 ejb2;
@Resource
UserTransaction utx;
public void startTransaction() {
try {
utx.begin();
} catch (NotSupportedException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public void commitTransaction() {
try {
utx.commit();
} catch (SecurityException e) {
throw new EJBException(e);
} catch (IllegalStateException e) {
throw new EJBException(e);
} catch (RollbackException e) {
throw new EJBException(e);
} catch (HeuristicMixedException e) {
throw new EJBException(e);
} catch (HeuristicRollbackException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public RemoteEJB2 getEJB2() {
return ejb2;
}
}
public class MyEJB2 implements RemoteEJB2{
@EJB
private RemoteEJB3 ejb3;
@Resource(name = "java:jboss/datasources/MyDS")
private DataSource ds;
public RemoteEJB3 getEJB3() {
return ejb3;
}
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void insertElement(String elementName) {
PreparedStatement pStat = null;
Connection con = null;
try {
con = ds.getConnection();
String sql = "insert into TRANSACTIONTEST(COL1,COL2) values(?,?)";
pStat = con.prepareStatement(sql);
pStat.setString(1, elementName);
pStat.setDouble(2, Math.random());
pStat.executeUpdate();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MyEJB3 implements RemoteEJB3{
@Resource(name="java:jboss/datasources/MyDS")
private DataSource ds;
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void updateElement(String newName) {
PreparedStatement pStat = null;
Connection con = null;
try{ con = getDs().getConnection();
String sql ="update TRANSACTIONTEST set COL1=?";
pStat = con.prepareStatement(sql);
pStat.setString(1, newName);
pStat.executeUpdate();
}catch(Exception ex){
ex.printStackTrace();
}finally{
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
тест:
public class MyTest{
public static void main(String[] args) throws Exception {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
MyEJB1 ejb1 = context.lookup("ejb:/EJBTrials/MyEJB1!edu.in.ejbinterfaces. RemoteEJB1?stateful");
ejb1.startTransaction();
RemoteEJB2 ejb2 = ejb1.getEJB2();
ejb2.insertElement (“Test”);
RemoteEJB3 ejb3 = ejb2.getEJB3();
ejb3.updateElement (“UpdatedTest”);
ejb1.commitTransaction();
}
}
Я бы идеально, как всей сделки (запись вставки в БД) должна быть завершена после вызова CommitTransaction() на RemoteEJB1 боба.
Я пробовал комбинировать BMT для EJB1 и CMT для EJB2 и EJB3, которые приводят к выбросу EJBTransactionRequiredException. Я попытался сделать все бобы BMT. Однако, согласно спецификации EJB3.1, BMT не может распространяться на несколько компонентов. Не могли бы вы сообщить мне какие-либо идеи/ссылки, которые я мог бы использовать для решения этой проблемы?
Reference Application Server: JBOSS AS 7.1
Как сервер должен связывать 'ejb1' с экземплярами' ejb2'? Правда, у них есть один и тот же аутентифицированный пользователь, но насколько сервер знает, что они могут быть вызваны из совершенно разных, несвязанных программ. Вам нужно будет вызвать методы 'ejb2' и' ejb3' через 'ejb1'. – SJuan76
EJB1, EJB2, EJB3 представляют интерфейсы и объекты стандартной спецификации API. Следовательно, контракт на методы привязан, и я не имею свободы в плане изменений. Одним из основных требований спецификации API является возможность реализации модели и интерфейса для поддержки транзакции, а управление транзакциями будет оставаться у конечного пользователя моего вывода –
Я это знаю. Вопрос в том, что сервер не знает вашего кода и не знает другого способа узнать, что разные компоненты логически связаны, поэтому он не знает, являются ли они частью одной транзакции. Вы можете управлять транзакцией внутри EJB с состоянием, потому что тогда сервер знает, что методы связаны (потому что вы используете один и тот же EJB). – SJuan76