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".

Reply via email to