2013-10-28 2 views
0

У меня есть требование попытаться добиться распространения транзакций по нескольким фазам с состоянием. У меня есть 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

+0

Как сервер должен связывать 'ejb1' с экземплярами' ejb2'? Правда, у них есть один и тот же аутентифицированный пользователь, но насколько сервер знает, что они могут быть вызваны из совершенно разных, несвязанных программ. Вам нужно будет вызвать методы 'ejb2' и' ejb3' через 'ejb1'. – SJuan76

+0

EJB1, EJB2, EJB3 представляют интерфейсы и объекты стандартной спецификации API. Следовательно, контракт на методы привязан, и я не имею свободы в плане изменений. Одним из основных требований спецификации API является возможность реализации модели и интерфейса для поддержки транзакции, а управление транзакциями будет оставаться у конечного пользователя моего вывода –

+0

Я это знаю. Вопрос в том, что сервер не знает вашего кода и не знает другого способа узнать, что разные компоненты логически связаны, поэтому он не знает, являются ли они частью одной транзакции. Вы можете управлять транзакцией внутри EJB с состоянием, потому что тогда сервер знает, что методы связаны (потому что вы используете один и тот же EJB). – SJuan76

ответ

0

Не могли бы вы дайте мне знать о каких-либо идей/ссылки, которые я мог бы использовать, чтобы решить эту проблему?

Если я правильно понимаю вашу проблему, то вам необходимо назвать демаркацию управления транзакциями, управляемую клиентом. UnLike Container Maneged Transaction, в этом случае клиент отвечает за установление границ транзакции (запуск и фиксация/откат транзакции). Вы можете получить некоторые идеи о том, как его реализовать. here.

+0

Спасибо. Содержание в ссылке помогло мне решить проблему. Дополнительное чтение для JBOSS AS7: [link] (http://wildfly-development.1055759.n5.nabble.com/UserTransaction-used-by-remote-clients-td5541554.html) –

Смежные вопросы