Ho un qualcosa di simile senza stato di fagioli:EJB3 transazione Propagazione
@Stateless
public class MyStatelessBean implements MyStatelessLocal, MyStatelessRemote {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.SUPPORTED)
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.process(obj);
}
}
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
La tipicamente utilizzo, allora è il client chiamerebbe processObjects (...), che in realtà non interagisce con il gestore di entità. Fa ciò che deve fare e chiama il processo (...) individualmente per ogni oggetto da elaborare. La durata del processo (...) è relativamente breve, ma processObjects (...) potrebbe impiegare molto tempo per eseguire tutto. Quindi non voglio che mantenga una transazione aperta. I do richiedono le singole operazioni del processo (...) per operare all'interno della propria transazione. Questa dovrebbe essere una nuova transazione per ogni chiamata. Infine, vorrei mantenere l'opzione aperta per il client per chiamare il processo (...) direttamente.
Ho provato un certo numero di diversi tipi di transazione: mai, non supportato, supportato (su processObjects) e richiesto, richiede nuovo (processo) ma ricevo TransactionRequiredException ogni volta che viene chiamato merge().
Sono stato in grado di farlo funzionare suddividendo i metodi in due fagioli differenti:
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
@EJB
private MyStatelessBean2 myBean2;
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.myBean2.process(obj);
}
}
}
@Stateless
public class MyStatelessBean2 implements MyStatelessLocal2, MyStatelessRemote2 {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
ma io sono ancora curioso di sapere se è possibile ottenere questo risultato in una classe. Mi sembra che il gestore delle transazioni funzioni solo a livello di bean, anche quando ai singoli metodi vengono fornite annotazioni più specifiche. Quindi, se contrassegno un metodo in modo da impedire che la transazione inizi a chiamare altri metodi all'interno della stessa istanza, non creerà una transazione, indipendentemente dal modo in cui vengono contrassegnati?
Utilizzo JBoss Application Server 4.2.1.GA, ma le risposte non specifiche sono benvenute/preferite.
Ho solo pensato di passare alla discussione e, visto che ho fatto questa domanda, questo problema è emerso diverse volte (incidentalmente, il mio capo ha detto di aver trovato questa domanda via Google una volta mentre cercava di risolverlo da sé.) Abbiamo usato questa soluzione un certo numero di volte, quindi grazie ancora. –
Penso che questa sia una buona domanda da sapere. Ti aspetti queste semantiche se mai dovessi fare qualcosa dal mondo EJB2, ma potrebbero sembrare un po 'straniere se hai lavorato solo in EJB3. Un altro modo per vedere le cose è che devi assicurarti che il metodo che stai chiamando sia chiamato * attraverso l'interfaccia EJB *. – cwash