EJB3-Transaktionsausbreitung

Ich habe eine zustandslose Bohne wie:

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

Die typische Verwendung ist dann, dass der Client processObjects (...) aufruft, das eigentlich nicht mit dem Entitätsmanager interagiert. Es tut, was es tun muss, und ruft process (...) für jedes zu verarbeitende Objekt einzeln auf. Die Dauer von process (...) ist relativ kurz, aber processObjects (...) kann sehr lange dauern, um alles zu durchlaufen. Daher möchte ich nicht, dass eine offene Transaktion aufrechterhalten wird. ichtun müssen die einzelnen Prozessvorgänge (...) innerhalb ihrer eigenen Transaktion ausführen. Dies sollte eine neue Transaktion für jeden Anruf sein. Zuletzt möchte ich die Option für den Client offen halten, um process (...) direkt aufzurufen.

Ich habe eine Reihe verschiedener Transaktionstypen ausprobiert: nie, nicht unterstützt, unterstützt (in processObjects) und erforderlich, erfordert neue (in process), aber ich erhalte die TransactionRequiredException jedes Mal, wenn merge () aufgerufen wird.

Ich habe es geschafft, indem ich die Methoden in zwei verschiedene Beans aufgeteilt habe:

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

aber ich bin immer noch neugierig, ob es möglich ist, dies in einer Klasse zu erreichen. Für mich sieht es so aus, als würde der Transaktionsmanager nur auf Bean-Ebene arbeiten, auch wenn einzelne Methoden spezifischere Anmerkungen erhalten. Wenn ich also eine Methode so markiere, dass verhindert wird, dass die Transaktion andere Methoden innerhalb derselben Instanz aufruft, wird auch keine Transaktion erstellt, unabhängig davon, wie sie markiert sind.

Ich verwende JBoss Application Server 4.2.1.GA, aber unspezifische Antworten sind willkommen / bevorzugt.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage