Thanks Doug! This really helps, and is a neat solution to this ugly
problem.
I understand your point about SessionSynchronization not making my
non-transactional datasource transactional, but it does come pretty close,
and I have a manual intervention step in the case of a stuff-up (basically
any problems encountered during AfterCompletion are emailed to someone,
and they would have to manually patch the data, shouldn't happen, but at
least there is a solution in place).
Would you mind explaining how I can get a normal Java object
"registered as a listener to the Transaction"? I cannot remember seeing
anything about this in the spec, and UserTransaction doesn't seem to have
any way to do this.
> In general, I've found very little practical use for the Stateful
> Session Bean which implements SesssionSynchronization.
Isn't my problem (updating a non-transactional datasource) THE practical use
for it?
Also, as I had to note all this down in our bug tracker, I thought I would
paste in my notes on your first solution below for list posterity.
Thanks,
Craig
----------------------------------------------------------------------
--------------- STATELESS FRONT END ------------------
/**
* @ejb:interface-method
* @ejb:transaction="NotRequired" <<<<<<
*/
public void someMethod(String arg1)
{
StatefulEJBLocal sfsb = StatefulEJBUtil.getLocalHome().create();
StatelessEJBLocal slsb = StatelessEJBUtil.getLocalHome.create();
slsb.anotherMethod(sfsb,arg1);
sfsb.remove();
}
slsb.anotherMethod() MUST have transactional scope, and it MUST do ALL
the transactional stuff required in someMethod()!!! someMethod()'s only
responisbility is creating sfsb!
-------------------------------------------------------
---------------- STATEFUL FRONT END -------------------
private StatefulEJBLocal sfsb;
public void setEntityContext() {
StatefulEJBLocal sfsb = StatefulEJBUtil.getLocalHome().create();
}
/**
* @ejb:interface-method
* @ejb:transaction="Requires" <<<<<<
*/
public void someMethod(String arg1)
{
StatelessEJBLocal slsb = StatelessEJBUtil.getLocalHome.create();
slsb.anotherMethod(sfsb,arg1);
}
public void ejbRemove() {
sfsb.remove();
}
--------------------------------------------------------
On Wed, 17 Jul 2002, Doug Bateman wrote:
> On Tue, 16 Jul 2002 19:22:54 +1000, Craig O'Shannessy <[EMAIL PROTECTED]> wrote:
>
> >Hi,
> >
> >I wonder if someone could clear up a problem for me. It seems that a
> >Stateless session bean cannot really use a Stateful session bean for
> >two reasons.
>
> A Stateful Session Bean can indeed be called from a Stateless Session Bean. Read on.
>
> >1. The stateless bean cannot call remove on the stateful, therefore can't
> > clean it up (see code below)
>
> You're right in that the Stateful Session Bean using Session Synchronization cannot
>be destroyed while it's still participating in a transaction, because then the bean
>would be destroyed before finding out the final results of the transaction it's
>listening to. However, you can work around this problem by creating the Stateful
>Session Bean before the transaction starts, and destroying it after the transaction
>completes. You'd then pass that stateful session bean as a parameter to the
>stateless one.
>
> For example, the user could call session bean A (which would have it's transaction
>attribute set to NOT_REQUIRED) which creates the Stateful Session Bean and then calls
>session bean B (with transaction attribute REQUIRED or REQUIRES_NEW) and passes as an
>argument a reference to the stateful bean. When the call to session bean B returns,
>the stateful session bean is notified of the results of the transaction. Bean A
>would then proceed to clean up the stateful bean. Alternatively the client itself
>could perform the duties of Session Bean A by creating (and later destroying) the
>stateful session bean and then passing it as an argument to Session Bean B.
>
> >2. If the stateless bean holds onto a reference to a stateful bean to get
> > around creating one on each call and avoid problem 1., another problem
> > occurs. The Stateless bean can be shared between concurrent transactions
> > (see quote from spec below), therefore the stateful beans transactional
> > scope is indeterminate (cause nasty blocking or even overlapping
> > transactions?)
>
> This actually very much depends on the design. If the stateless session bean's
>transaction attributes are REQUIRES_NEW, then each call to the stateless bean would
>create a new transaction, which would complete IMMEDIATELY as the method calls
>return. Since the stateless session bean is still single threaded, it would be
>impossible for the stateful session bean to be participating in two transactions at
>once.
>
> Still, keeping this sort of conversational state as a field in your stateless
>session bean should be considered very bad design and avoided all together, even if
>that state were reinitialized on every call to the stateless bean.
>
> So your design choices are either to adopt the design I mentioned earlier, or to
>instead wrap your non-transactional resource in a regular java object which
>implements the javax.transaction.Sychronization interface and gets registered as a
>listener to the Transaction.
>
> >One reason you might want to use a Stateful bean from a Stateless is to
> >do SessionSyncronization on a non transactional datasouce for example.
>
> Keep in mind that just because your non-transactional resource is wrapped by a
>transactional session bean implementing session synchronization with the appropriate
>undo logic, this doesn't mean that your resource is truly transactional now. There
>can be scenarios where your undo code might fail (such as the resource going
>offline), and your stuck with a datastore in a non-deterministic state. Making a
>truly transactional resource requires implementing the Transaction_XA protocol and
>using a write ahead log, which ends up getting very, very complex.
>
> In general, I've found very little practical use for the Stateful Session Bean which
>implements SesssionSynchronization. It is my firm opinion that Stateful Session
>Beans, if used at all, should only be used to hold conversational state on behalf of
>the client (such as aggregating user input or sending the client a large result set
>in pages of 10 objects at a time). This means Stateful Session Beans should be
>restricted to the layer of your application called directly from the client, and
>should NEVER be called by another enterprise java bean.
>
> Doug
>
> P.S. I'm using the EJB-Interest web interface to send this e-mail, which does a
>poor job of poor line wrapping. My apologizes.
>
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".