To investigate this further I created an S2 webapp deployed within a
JBoss 4.2.0 container using EJB3 stateless session beans and JPA entity
beans.
First of all though, if you use JPA in standalone mode you can use the
open session in view pattern as discussed in prior emails. This
question relates to container managed persistence where you don't have
the same luxury of creating your own EntityManagerFactory within the webapp.
My short answer is: though is that Struts2 does not introduce any new
limitations. You can use struts2 within an EJB3 container with CMP and
lazy loading within the JSP the same way you do with with any other
webapp within an EJB3 container. You have to lookup the PersitanceUnit
in an interceptor as described at [1].
My long answer:
Test scenario;
I created an S2 action that looks up an a remote session bean to find a
list of books. The session been performs a simple EJB-QL query ("select
book from Book book")
Each Book is an Entity with a @OneToMany relatinoship to a BookAuthorMap
which in turn has a @ManyToOne to an Author. ie. effectively a
many-to-many relationship directed from book to author to provide a
genuine lazy-loading opportunity.
My action has a property List<Book> getBooks()
My JSP result displays the list of books found, with an inner iterator
to display the list of authors mapped to each book.
Effectively, each inner iteration causes a lazy load of the referenced
map and Author if the entity's not already cached by the EntityManager.
Simple enough?
Here's my summary:
a. as you'd expected, you can't use EJB3 DI within your S2 actions
(@PersistenceContext, @Resource, @EJB)
However, you can use JNDI so there's no reason why these can't be
supported via an explict S2 plugin or interceptor.
Easy options are:
- write a custom annotation and interceptor as discussed at [2]
- use a Guice object factory with a JNDI provider to inject
- use a Spring object factory to do the same thing
- write a Struts2 EJB3 plugin to recognise @PersistenceContxt,
@Resource @EJB in actions and inject them
(my action simply created an InitialContext and looked up the EJB
session bean0
b. As you would expect, the container determines that the transaction is
over when the ejb call ends and the entities become detached from the
EntityManager So lazy loading is not available in the action (or JSP),
but this was when it occurred to me that this is in no way related to
struts2 - it's the same problem that exists in stand-alone JPA, and the
same problem exists for plain JSP, or plain servlets, struts1 and pretty
much anything else in an EJB container (except perhaps JSF backed by
managed beans, which I don't know anything about).
So the question is not whether struts2 has a limitation - it doesn't.
The question should be how you can extend the transaction down into the
web-tier in an EJB environment.
And the answer is simply to use JDNI to lookup the PersistenceUnit in an
interceptor or filter - the same as you do for stand-alone mode except
using a lookup. I haven't tried yet, but its described at [1].
Hope that helps,
Jeromy Evans
References:
1.
http://weblogs.java.net/blog/ss141213/archive/2005/12/dont_use_persis_1.html
2.
http://www.nabble.com/Re:--s2--Struts-Dependency-Injection-and-EJB3---support---or-how-can-i-Do-it--p8512920.html
Caine Lai wrote:
Hi Jeromy,
Thanks for your response. It sounds like your solution works, but it
doesn't seem like this would integrate with container managed persistence
very well.
It's strange this is so difficult to achieve in the "next generation"
struts. I don't know why JPA/EJB3 is an afterthought. I really don't
want
to abandon Struts 2 at this point since it was exactly what I was looking
for except for this one very large issue.
I'd still be very interested in hearing from anyone that has thought
about
or solved this problem of using Struts 2 in a managed environment.
Thanks,
Caine
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]