EJB3 Transag Propagation

Mam bezpaństwową fasolę w stylu:

@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();
    }
}

Zazwyczaj używa się wtedy, gdy klient wywołuje processObjects (...), który w rzeczywistości nie wchodzi w interakcję z menedżerem encji. Robi to, co musi zrobić, i wywołuje proces (...) indywidualnie dla każdego obiektu do przetworzenia. Czas trwania procesu (...) jest stosunkowo krótki, ale obiekty processObject (...) mogą zająć bardzo dużo czasu. Dlatego nie chcę, aby utrzymywała otwartą transakcję. jarobić potrzebują operacji indywidualnych (...) do działania w ramach własnej transakcji. To powinna być nowa transakcja dla każdego połączenia. Na koniec chciałbym pozostawić otwartą opcję, aby klient mógł wywołać proces (...) bezpośrednio.

Wypróbowałem wiele różnych typów transakcji: nigdy, nie obsługiwane, obsługiwane (na processObjects) i wymagane, wymaga nowego (w procesie), ale otrzymuję TransactionRequiredException za każdym razem, gdy wywoływane jest scalanie ().

Udało mi się to zrobić, dzieląc metody na dwie różne fasole:

@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();
    }
}

ale wciąż jestem ciekawy, czy można to osiągnąć w jednej klasie. Wygląda na to, że menedżer transakcji działa tylko na poziomie komponentu bean, nawet jeśli poszczególne metody mają bardziej szczegółowe adnotacje. Jeśli więc zaznaczę jedną metodę w taki sposób, aby uniemożliwić rozpoczęcie transakcji innym metodom w tej samej instancji, nie utworzy się transakcji, bez względu na to, jak są one oznaczone?

Używam JBoss Application Server 4.2.1.GA, ale nieswoiste odpowiedzi są mile widziane / preferowane.

questionAnswers(8)

yourAnswerToTheQuestion