Laird Nelson wrote:
> Ideally I'd love to be able to encapsulate this in a session bean. But
> of course I can't (<vendor>except in WebLogic, thank God; yet another
> reason I'm personally leaning that way</vendor>) start a raft of threads
> working on these precondition tasks, join up with them when they're
> done, and test their results. (Note that of course the creation of many
> threads that perform what are essentially read-only checks and then join
> up with the main one does not result in any transactional no-nos,
> providing a nice counterexample to the "the EJB server must control all
> threads" dogma.)
Laird, I feel your pain! ;-)
We did something very similar with on a previous client's project. We
needed to load up the set of a customer's accounts from a mainframe.
This retrieval required screen-scraping, and each account could take a
few seconds. For a customer with 40 accounts, it took too long. But
we had a couple hundred available connections to the mainframe, so
parallel access was a good design choice.
We also did it in WebLogic. The session bean spawned off threads to
access the accounts. We implemented a small thread pool to make sure
that we didn't create too many threads and choke off the container. We
were careful that our threads did not cross any boundary where the
thread context (security, transaction) was needed by the container. We
made sure all threads joined up (or were otherwise cleaned up) before
the session bean call returned. It worked well (and is still working
well AFAIK).
> How then should I accomplish this task if I'm going to be specification
> compliant? It looks like if I wanted to be a good EJB1.1 citizen, I'd
> have to move each precondition step into its own session bean (eeeYUCK)
> and call them all from a multithreaded client (double eeeYUCK)--the
> client now becomes the place where the *real* workflow occurs (triple
> eeeYUCK), not the session bean. This seems faintly or strongly wrong to
> me (depending on how ornery I'm feeling at the moment). Comments?
> Surely the EJB specification should allow for "workflows" like this.
The only way I know of to be compliant with current specs, is to
implement the parallel processing outside the container. Either, as
you suggest, have the client be multi-threaded and access distinct
service beans, or have a single bean that calls out to an RMI object
that implements the parallelism. I think this second choice is still
standards-compliant. Both of these approaches aren't ideal. If the
multi-threading is in the client, then we are forced to split out at
least some of the processing algorithm out to the server. A separate
RMI object adds the overhead of another remote call, plus we can't
take advantage of cool app server features like load balancing and
fail over.
When we were exploring the above design we had two other options. The
first was to implement something similar to a J2EE connector. We
call into the connector to load all the accounts for a customer and it
would do whatever it needed to return the set of accounts, including
the parallel screen-scraping operation. But of course J2EE connectors
are not yet specified (not publicly), and there's no way to install
one into a container in a semi-standard way. With WebLogic, we could
implement this connector as a start up class, but this really didn't
buy us much over just implementing it in the session bean. Your
requirements are a bit different than parallel resource access, and
they don't map as well into the connector concept, so it would be
stretching the connector paradigm a bit for you to use this approach.
The second option was to use JMS. JMS isn't integrated with EJB yet
in a standard way, but WebLogic has a JMS implementation that seems to
work well with EJBs in their container. We could send out a JMS
message for each account to load (in your case for each precondition
check) and have a JMS session pool process the messages in parallel.
There's still the issue of how to coordinate the multiple responses
that come back, because the main session bean thread needs to wait
until all the responses come back before continuing (a "JMS join?").
We didn't choose this approach because it just seemed really round-
about to emit and catch messages just to do the parallelism. JMS
seems better suited to true inter-component messaging. It's possible
this approach could have some performance penalties from the JMS
services as well (we didn't benchmark it, though).
My opinion is that if the requirements really call for parallelism
in the middleware (EJBs), right now under the current specs, our
best option is to just go with the multi-threading. We have to
choose a container that lets us do it, and make sure we understand
the container implementation well enough to properly exploit it. The
threading design has to be well-behaved (thread pools, don't try to
access context-dependent resources, join before returning from EJB
calls, etc.). And our application design should encapsulate the
threading parts so that moving to another container, or moving to
some specified threading model in the future, doesn't cause massive
rework. It can be done. It's not standards-compliant. It has some
risks involved. That's my $0.02 USD.
-Paul Hodgetts
===========================================================================
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".