0 Replies Latest reply on Jul 16, 2004 6:41 AM by nvp_saradhi

    JTA Transaction problem with remote JBoss instance

      Hi All,

      I am facing the problem with transactions across remote JBoss servers. The scenario is like this:

      I have a SLSB deployed on JBoss server A which is running on machine X and I have an Entity Bean deployed on JBoss server B which is running on machine Y. Now I am invoking one of the business methods on SLSB using the client program on machine X and which in turn look up the BMP Entity Bean on machine Y and inserts a row into the database. And the session bean inserts a row into the database on machine X with the same info. of the created row in database on machine Y.

      I am using the JTA API in Bean Managed SLSB to manage these database updates atomically. The problem is after the SLSB invoking the Entity Bean's create method, a new row is inserted into the database on machine X, but the JBoss server A throws the following exception and rolled back the transaction on machine Y's database.

      [TxInterceptorBMT] Application error: BMT stateless bean TestEJB should complete transactions before returning (ejb1.1 spec, 11.6.1)

      Please find the files I am using for reference:
      SLSB code:
      -------------

      public int insertRow(String id) {
      Connection conn = null;
      UserTransaction ut = null;
      PreparedStatement pst = null;
      ResultSet rs = null;
      int result = 0;
      try {
      Properties prop = new Properties();
      prop.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
      prop.setProperty(Context.PROVIDER_URL, "jnp://remote-host:1099");
      initCtx = new InitialContext(prop);
      ut = sessionCtx.getUserTransaction();
      ut.begin();
      AccountHome accHome = (AccountHome) PortableRemoteObject.narrow(initCtx.lookup("MyAccountHome"), AccountHome.class);
      Account account = accHome.create(id, 300);
      double amount = account.balance();
      conn = getConnection();
      pst = conn.prepareStatement("insert into test values(?,?)");
      pst.setString(1, id);
      pst.setDouble(2, amount);
      result = pst.executeUpdate();
      pst.close();
      conn.close();
      ut.commit();
      }
      catch(Exception e) {

      try {

      pst.close();
      conn.close();
      ut.rollback();
      }
      catch(SystemException se) {
      throw new EJBException("Rollback failed: " + se.getMessage());
      }
      catch(SQLException se) {
      throw new EJBException("Rollback failed: " + se.getMessage());
      }
      throw new EJBException("Transaction failed: " + e.getMessage());
      }
      return result;
      }

      ejb-jar.xml:
      --------------

      <?xml version="1.0"?>

      <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

      <ejb-jar>
      <enterprise-beans>

      <ejb-name>TestEJB</ejb-name>
      com.abc.examples.TestHome
      com.abc.examples.Test
      <ejb-class>com.abc.examples.TestBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Bean</transaction-type>

      </enterprise-beans>
      </ejb-jar>

      jboss.xml:
      ------------

      <?xml version="1.0" encoding="UTF-8"?>

      <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">


      <enterprise-beans>

      <ejb-name>TestEJB</ejb-name>
      <jndi-name>MyTestHome</jndi-name>

      </enterprise-beans>



      Entity Bean code:
      --------------------

      public String ejbCreate (String accountId, double initialBalance) throws CreateException {

      this.accountId = accountId;
      this.balance = initialBalance;

      Connection con = null;
      PreparedStatement ps = null;

      try {

      con = getConnection();
      ps = con.prepareStatement("insert into ejbAccounts (id, bal) values(?, ?)");
      ps.setString(1, accountId);
      ps.setDouble(2, balance);

      if (ps.executeUpdate() != 1) {
      throw new CreateException ("JDBC did not create any row");
      }
      return accountId;
      }
      catch (SQLException sqe) {

      try {
      ejbFindByPrimaryKey(accountId);
      }
      catch(ObjectNotFoundException onfe) {
      throw new CreateException ("SQLException: " + sqe);
      }
      throw new DuplicateKeyException("An Account already exists in the database with Primary Key " + accountId);
      }
      finally {
      cleanup(con, ps);
      }
      }

      private Connection getConnection() throws SQLException {
      InitialContext initCtx = null;
      try {
      InitialContext ctx = new InitialContext();
      DataSource ds = (javax.sql.DataSource) ctx.lookup("java:/DefaultDS");
      return ds.getConnection();
      } catch(NamingException ne) {
      throw new EJBException(ne);
      }
      finally {
      try {

      if(initCtx != null) initCtx.close();
      }
      catch(NamingException ne) {
      throw new EJBException("Error closing context: " + ne);
      }
      }
      }

      ejb-jar.xml:
      --------------

      <?xml version="1.0"?>

      <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

      <ejb-jar>
      <enterprise-beans>

      <ejb-name>beanManaged</ejb-name> com.abc.transaction.beanmanaged.AccountHomecom.abc.transaction.beanmanaged.Account
      <ejb-class>com.abc.transaction.beanmanaged.AccountBean</ejb-class>
      <persistence-type>Bean</persistence-type>
      <prim-key-class>java.lang.String</prim-key-class>
      False
      <resource-ref>
      <res-ref-name>jdbc/DefaultDS</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      </resource-ref>

      </enterprise-beans>
      <assembly-descriptor>
      <container-transaction>

      <ejb-name>beanManaged</ejb-name>
      <method-name>*</method-name>

      <trans-attribute>Required</trans-attribute>
      </container-transaction>
      </assembly-descriptor>
      </ejb-jar>

      How could I solve this problem? Any help is greatly appreciated as I am in the middle of the project. Thanks in advance.