[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openejb-cvs
Subject:    [jira] [Commented] (TOMEE-509) Injected extended EntityManager is not registered (cannot be used for
From:       "Donatas Ciuksys (JIRA)" <jira () apache ! org>
Date:       2012-10-30 10:42:12
Message-ID: 1043154124.44022.1351593732446.JavaMail.jiratomcat () arcas
[Download RAW message or body]


    [ https://issues.apache.org/jira/browse/TOMEE-509?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13486785#comment-13486785 \
] 

Donatas Ciuksys commented on TOMEE-509:
---------------------------------------

I'll try to explain why I'm so persistent :)

Imagine you'd like to implement some complicated/complex use-case that is of \
conversation type (i.e. some wizard, checkout procedure, etc.). By \
complicated/complex I mean that this use-case consist of 3-4 steps (imagine wizard \
steps) and EACH of them requires entering much of data and/or complex processing of \
that data and communication with DB. So approach to have one component implementing \
the whole use-case is not correct from OOAD/coupling/cohesion perspective. Programmer \
would be tended to have multiple components, for example, one for each use-case step \
(or at least more than one component). Now this is no longer documented obviously in \
EJB/JPA/CDI specs. I see two ways to implement such a use-case:

1. "Propagated extended EntityManager" way - one Facade @ConversationScoped Stateful \
EJB delegating business logic to other components. a) Create Stateful \
@ConversationScoped EJB that governs the conversation (but does not have business \
logic for separate steps). It declares @PersistenceContext(EXTENDED) EntityManager em \
(though might not use it at all itself). Lets call it Facade EJB.  Implement all the \
business logic methods within this Facade EJB that delegate calls to other business \
logic components. b) Create other business logic components (Stateless or \
@RequestScoped Stateful, depending on business logic semantics). They declare \
@PersistenceContext(TRANSACTIONAL), but always receive EntityManager from Facade EJB \
by PersistenceContext propagation/inheritance c) Create JSF page for each use-case \
step.  d) Apply strict limitations: all JSF pages are allowed to call ONLY Facade EJB \
(otherwise EntityManager will not be propagated); Facade EJB calls business logic \
components; business logic components do work and communicate with DB. Such \
limitations ensure, that all business components during the whole conversation are \
working with one and the same EntityManager instance (managed by Facade EJB).

If somebody thinks that limitations above are too strict (programmer thinks: "I want \
my JSF page to communicate with business logic component directly - I'm tired to \
write hundreds of business logic delegate methods within Facade EJB; CDI allows me to \
get rid of delegate methods, doesn't it???"):

2. "Injected extended EntityManager" way 
a) Create Stateful @ConversationScoped EJB that governs the conversation (but does \
not have business logic for separate steps). It declares \
"@PersistenceContext(EXTENDED) EntityManager em" and has a producer that returns this \
particular instance (NOT a new instance each time!!!) NO business logic delegate \
methods. b) Create other business logic components (Stateless or @RequestScoped \
Stateful, depending on business logic semantics). They declare "@Inject EntityManager \
em". In real-life we would create different qualifiers for different conversations \
(use-cases) too (I would like future CDI to support limited scope/namespace/module \
injection - not to inject anything from the whole world)  c) Create JSF pages
d) Almost none limitations: As soon as one JSF page touches busines logic component, \
it asks for injected EntityManager, Stateful @ConversationScoped bean gets created, \
produces EntityManager, and so on... (of course, conversation.begin() needs to be \
called, but this is not a problem).

No. 2 is better, because:
- no delegate methods are needed
- JSF pages call business components directly - less sophisticated code.

Up to now only Glassfish allows me to implement conversation use-case in 2. way. 
                
> Injected extended EntityManager is not registered (cannot be used for DB \
>                 operations)
> ------------------------------------------------------------------------------------
>  
> Key: TOMEE-509
> URL: https://issues.apache.org/jira/browse/TOMEE-509
> Project: TomEE
> Issue Type: Bug
> Affects Versions: 1.5.0, 1.5.1
> Environment: Windows 7 x64; jdk1.7.0_09 32 bit; \
>                 apache-tomee-1.5.1-20121026.064316-51-webprofile.zip
> Reporter: Donatas Ciuksys
> Priority: Critical
> 
> 1. Create class EntityManagerProducer:
> @SessionScoped
> @Stateful
> public class EntityManagerProducer implements Serializable {
> 
> @PersistenceContext(type=PersistenceContextType.EXTENDED)
> private EntityManager em;
> 
> @Produces
> public EntityManager getEntityManager() {
> return em;
> }
> }
> 2. Create injection client:
> @Named
> public class A {
> 
> @Inject
> private EntityManager em;
> public String getDelegateClassName() {
> return em.getDelegate().getClass().getCanonicalName();
> }
> 
> }
> 3. Create JSF page and try to call getDelegateClassName():
> <h:body>
> EntityManager is open: #{a.delegateClassName}
> </h:body>
> 4. Deploy (successful) and run the application - observe error message (printed in \
> browser): An Error Occurred:
> InternalError: an entity manager should already be registered for this extended \
> persistence unit viewId=/index.xhtml
> location=D:\dev\proj\templates\InjectionDemo\build\web\index.xhtml
> phaseId=RENDER_RESPONSE(6)
> Caused by:
> java.lang.IllegalStateException - InternalError: an entity manager should already \
> be registered for this extended persistence unit at \
> org.apache.openejb.persistence.JtaEntityManagerRegistry.getEntityManager(JtaEntityManagerRegistry.java:99)
>                 
> - Stack Trace
> java.lang.IllegalStateException: InternalError: an entity manager should already be \
> registered for this extended persistence unit  at \
> org.apache.openejb.persistence.JtaEntityManagerRegistry.getEntityManager(JtaEntityManagerRegistry.java:99)
>   at org.apache.openejb.persistence.JtaEntityManager.getEntityManager(JtaEntityManager.java:80)
>   at org.apache.openejb.persistence.JtaEntityManager.getDelegate(JtaEntityManager.java:114)
>   at org.apache.openejb.persistence.JtaEntityManager.getDelegate(JtaEntityManager.java:53)
>   at beans.A.getDelegateClassName(A.java:19)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> ...

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic