HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Starting a new transaction inside a single bean

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
startingnewbeansingletransactioninside

Problem

I thinking of a way to start a new transaction inside a single EJB bean. Typical use case would be to process every item from a list in a separate transaction.

One way to do it would be to use UserTransaction:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class ManagerBean implements Manager {
    @Resource
    private UserTransaction tx;

    @Override
    public void processAll(List list) throws Exception {
        for (Object obj : list) {
            tx.begin();
            try {
                processOne(obj);
                tx.commit();
            } catch (Exception ex) {
                tx.rollback();
            }
        }
    }

    private void processOne(Object obj) {
        /* ... */
    }
}


But I find it error prone to directly use commit() and rollback(). I'd prefer to leave transaction handing to the container. So I've come up with this pattern:

ManagerBean.java

@Stateless
public class ManagerBean implements Manager, ManagerInternal {
    @Resource
    private SessionContext context;

    @Override
    public void processAll(List list) {
        ManagerInternal txThis = context.getBusinessObject(ManagerInternal.class);
        for (Object obj : list) {
            txThis.processOne(obj);
        }
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void processOne(Object obj) {
        /* ... */
    }
}

@Local
interface ManagerInternal {
    void processOne(Object obj);
}


Manager.java:

@Local
public interface Manager {
    void processAll(List list);
}


Though I'm unsure if it's ok to have package-private local interface. It works on JBoss 4.2, but I don't know about other app servers.

What do you think about this pattern?

Alternative using self-injection:

Instead of using SessionContext.getBusinessObject(interface) I suppose you can inject EJB into itself:

ManagerBean.java

```
@Stateless
public class ManagerBean implements Manager

Solution

Variable Names:

Your variable names are very generic. The List you pass in is just called list. This might be fine at coding-time, but as soon as you have to analyze the code weeks or maybe even months later, you will probably wonder, what purpose that list serves.

I'd thus propose you change the variable name a bit. Something like listForPersisting or something should be fine ;) The same may apply to your UserTransaction and the SessionContext, but as they are defined enough by their typename, that shouldn't be a big problem.
Spacing / Comments

I realy like your spacing. Your code is speaking enough, that you can leave out comments and still you understand it on first reading.

That's very good, keep it up!
Approach

I don't think you can solve your specific problem in many other ways as elegantly as you did.

What I do not like about your code is that you needlessly create the interface ManagerInternal as if you needed a function to override.

You name that interface "Internal" and go through the hassle of making it @Local. But then you do something totally incomprehensive. You expose the overriden method.

If you don't need the method anywhere else, the principle of information hiding applies.

In computer science, information hiding is the principle of segregation of the design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed. The protection involves providing a stable interface which protects the remainder of the program from the implementation (the details that are most likely to change).

Written another way, information hiding is the ability to prevent certain aspects of a class or software component from being accessible to its clients, using either programming language features (like private variables) or an explicit exporting policy.

Context

StackExchange Code Review Q#35926, answer score: 5

Revisions (0)

No revisions yet.