I have a requirement of trying to achieve transaction propagation across multiple stateful beans I have 3 Stateful EJB;s in my application.. The start and end transaction is controlled be an external java application through remote interface method invocation.
@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();
}
}
}
}
Test Class:
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();
}
}
I would ideally like the whole transaction(record insertions in db) to be completed after invocation of commitTransaction() on RemoteEJB1 bean.
I tried combination of BMT for EJB1 and CMT for EJB2 and EJB3 which lead to EJBTransactionRequiredException being thrown I tried to make all beans as BMT. However according to EJB3.1 spec BMT cannot be propagated across multiple beans. Could you let me know of any ideas/links which I could use to solve this problem?
Reference Application Server : JBOSS AS 7.1
ejb1withejb2instances? True, they have the same authenticated user, but as far as the server knows they could be being called from completely different, unrelated programs. You will need to call theejb2andejb3methods throughejb1. - SJuan76