I have a CDI bean that is being invoked by an event chain outside of the web container. It is responding to entity changes performed server side, and trying to parse them and update clients. I originally used DataTools.getProperties to get fields from the entity into a real time message to the client. However, for entities that have bi directional relationships, that particular tool does not break the recursion caused by the relationship, which ends up causing problems on the client. While investigating I found that when doing a fetch against these entities, these recursive relationships are broken as expected, and so I decided to use DataSource.getProperties in an attempt to resolve this issue. However, I end up with the following exception because emf provider is not being invoked from the context it expects when making the jndi lookup. Is there some other way that I am missing to retrieve a DataSource instance from outside of the web context?
Announcement
Collapse
No announcement yet.
X
-
DataSourceManager fails to find entity manager in cdi bean
Last edited by jpappalardo; 24 Sep 2014, 10:56.Tags: None
-
I was able to confirm that the issue is performing the jndi lookup from the cdi context rather than web application context. I have a servlet that on init actually sends an event that the cdi bean listens to for creation (it is application scoped), thus ensuring that the servlet container has started, and your init and pre cache servlets have executed prior to trying to send updates to the client, as entity changes are made during the startup process. So I implemented a hack in the servlets init function to create a map of DataSource objects, that the cdi bean could then use directly. Unfortunately, when the datasource runs into a property with a related datasource, I get the same error as it attempts to create the related ds.
Comment
-
Having your own EMFProvider seems to be the best choice for your setup.
You can implement com.isomorphic.jpa.EMFProviderInterface or extend one of the existing EMFProvider implementations and change its functionality. That way you will gain control over creation/lookup of EntityManager.
You will need to use jpa.emfProvider setting in server.properties to make Smartclient use your provider implementation.
Comment
-
I have an implementation that appears to be working, but for the sake of ensuring that I am not causing an unforeseen issue can you review this code?
EMFProviderBean:
EMFProviderImpl:
jpa.emfProvider: com.sncorp.gs2.gsui.server.datasource.EMFProviderImplLast edited by jpappalardo; 24 Sep 2014, 09:03.
Comment
-
Your implementation misses code for get/commit/rollback transaction methods. You could either implement those yourself accordingly to EMFProviderInterface javadoc requirements for those methods or partly use one of existing implementations.
I'd suggest extending EMFProviderLMT - EMF provider for Locally Managed Transactions. Just as you did originally in your implementation override get and getEntityManager methods, and leave the rest for super class.
Code:public class EMFProviderImpl extends EMFProviderLMT { private final EMFProviderBean emfProviderBean; public EMFProviderImpl() { emfProviderBean = CDI.current().select(EMFProviderBean.class).get(); } @Override public EntityManagerFactory get() { return emfProviderBean.getEmf(); } @Override public EntityManager getEntityManager() throws PersistenceException { return emfProviderBean.getEm(); } }
Comment
-
That is not a logical solution because I am injecting the EMF and EM, so they are container managed, so perhaps I should be extending CMT? I tried doing as you requested and it blows because a JTA EntityManager cannot use getTransaction. The injected em, or an em created via the injected emf returns an EntityTransaction rather than a UserTransaction.
Comment
-
This on the other hand does appear to work succesfully, though am I supposed to do something in getTransaction if em is not null?
***EDIT***
To answer my own question I believe this is appropriate
*** EDIT 2 ***
The above does not work because there is no transaction to join, the transaction only exists within the boundaries of the EMFProviderBean methods, so exceptions are thrown by em.joinTransaction. I am having a really hard time making sense of how I can provide for container managed transactions and access to the emf/em regardless of the context I am in.Last edited by jpappalardo; 24 Sep 2014, 09:03.
Comment
-
Can you please provide some explanation on how exactly one is supposed to use EMFProviderCMT?
I cannot seem to resolve the appropriate way to do so.
server.properties
Code:jpa.emfProvider: com.isomorphic.jpa.EMFProviderCMT jpa.entityManager: persistence/em jpa.entityManagerFactory: persistence/emf
GSUIEntityEventObserver.java
I presume from your documentation this should make it such that I can succesfully use DataSource.getProperties via an EJBContext however I now get the following errors when trying to do a simple fetch
FetchOnlyJPA2DataSource
From what I am observing it would seem that my custom datasource needs to be @Stateless, however I cannot find any property I can set on the ds.xml to provide a factory so that the custom ds is actually container managed. What am I missing here?Last edited by jpappalardo; 24 Sep 2014, 09:04.
Comment
-
The stack trace you've shown contains all the answers. It says: "No EjbContext available as no EJB invocation is active"
I understand that you do not have an EJB context, i.e. at the moment of execution EJB context cannot be get via lookup. You may check this yourself by trying to execute code shown below for example via DMI or similar.
Code:EJBContext ctx = (EJBContext) new InitialContext().lookup("java:comp/EJBContext");
Another notice about the stacktrace - EJB is not there, if you were working in EJB environment I expect to see its classes in stacktrace which is not the case. This allows to think that may be you did not configure your EJB application correctly and your application is running on EJB server, but just as simple Web application.
Comment
-
This implementation seems to work well:
EMFProviderBean
EMFProviderImplLast edited by jpappalardo; 24 Sep 2014, 09:05.
Comment
Comment