patternjavaMinor
Starting a new transaction inside a single bean
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
But I find it error prone to directly use
ManagerBean.java
Manager.java:
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
ManagerBean.java
```
@Stateless
public class ManagerBean implements Manager
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
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
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
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.
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.