-
1. Re: How to get EntityManager instance in a component marked @Startup
purecharger Mar 26, 2010 6:09 PM (in response to purecharger)I found that I can explicitly retrieve an entityManager instance by doing:
EntityManager em = (EntityManager)Component.getInstance("entityManager");
Then, just to test this out, I am doing this:
User u = new User(); u.setFirstName("joe"); u.setMiddleName(""); u.setLastName("blow"); u.setUsername("jblow"); u.setPin("1234"); em.persist(u);
However, the new User is never persisted. My User entity is properly written, because I am able to login against the rows stored in the database, with the same User object.
I attempted to add em.flush() to my code, but then a javax.persistence.TransactionRequiredException is thrown, with the message no transaction in progress.
I tried to change the FlushModeType to no avail, then read that for a given persistence unit, any pending commits will be written to the database prior to a query executing. So I attempted to login to my application (which performs a query against an injected EntityManager instance) for my newly created user, and sure enough, login fails, no user found.
Any ideas?
Thanks,
Ryan -
2. Re: How to get EntityManager instance in a component marked @Startup
kapitanpetko Mar 27, 2010 5:49 PM (in response to purecharger)Instead of using PostConstruct, write an observer for org.jboss.seam.postInitialization and do your processing there. To make things easier use an EJB and @PersitenceContext, that would handle transactions properly. There is no point in using the SMPC for your use case.
HTH
-
3. Re: How to get EntityManager instance in a component marked @Startup
swd847 Mar 29, 2010 6:00 AM (in response to purecharger)Try this:
@Startup @Scope(ScopeType.APPLICATION) @Name("vsContest") public class VsContext { @In private EntityManager entityManager; @Create @Transactional public void initialize() { User u = new User(); u.setFirstName("joe"); u.setMiddleName(""); u.setLastName("blow"); u.setUsername("jblow"); u.setPin("1234"); entityManager.persist(u); entityManager.flush(); } }
-
4. Re: How to get EntityManager instance in a component marked @Startup
purecharger Mar 29, 2010 8:15 PM (in response to purecharger)Nikolay/Stuart-
Thank you very much for your help, I believe this will work however I have not tried it yet because I changed the structure of my application since the original post. I still have the vsContext component annotated with @Startup, and my initialization method is changed to be an @Observer for postInitialization, but now what I am doing is using the Factory pattern to retrieve a
user credentials processor
object. It is in this object now that I need to utilize the entity manager:public interface CredentialsProcessor { public void process(InputStream in); }
and for a CSV file:
@Scope(APPLICATION) @Name("csvCredentialsProcessor") public class CSVCredentialsProcessor implements CredentialsProcessor { @In private EntityManager entityManager; public void process(InputStream in) { ... } }
My factory class is a standard impl that keeps a single instance of CredentialsProcessor for each type of credentials file that we accept.
But I think I am going against the Seam component model by managing my own instances with the factory pattern. What is the proper way to do this with seam? Because I need the flow of control to proceed from my component annotated @Startup, to retrieving the proper CredentialsProcessor impl, and having access to an EntityManager.
Thanks!
-
5. Re: How to get EntityManager instance in a component marked @Startup
purecharger Mar 29, 2010 10:57 PM (in response to purecharger)I've attempted to use Nikolay's suggestion of EJB w/PersistenceContext, and I feel like I'm back to square one: no EntityManager is injected.
Here is my factory:
public class CredentialsProcessorFactory { private static Map<CredentialsType, CredentialsProcessor> PROCESSORS = new HashMap<CredentialsType, CredentialsProcessor>(); static { PROCESSORS.put(CredentialsType.CSV, new CSVCredentialsProcessor()); } private CredentialsProcessorFactory() {} public static CredentialsProcessor getProcessor(CredentialsType type) { CredentialsProcessor p = PROCESSORS.get(type); if(p == null) throw new IllegalArgumentException("No CredentialsProcessor registered for type " + type.toString()); return p; } }
There is only a single CredentialsProcessor in the factory store as of now, a CSVCredentialsProcessor. I've made this an EJB:
@Local public interface CredentialsProcessor { public void process(InputStream in); }
@Stateless public class CSVCredentialsProcessor implements CredentialsProcessor { @PersistenceContext private EntityManager entityManager; public void process(InputStream creds) { ... } }
After my instance is returned via CredentialsProcessorFactory.getProcessor(CredentialsType.CSV), the entityManager instance is still null.
I really feel like I'm fighting Seam here, way more than I should be. Do I need to give up, and make every single object a component?
-
6. Re: How to get EntityManager instance in a component marked @Startup
purecharger Mar 30, 2010 1:22 AM (in response to purecharger)I should have waited before posting. So obviously the instance I am instantiating and storing in the static Map is not managed by JBoss and will not have any interception or injection performed on it.
Explicit lookup of the SLSB from JNDI returns an instance that has the EntityManager injected properly.
My question now becomes: with EJB3 and JBoss what is corresponding Factory pattern? I'd like to continue to be able to use the CredentialsType enum to lookup the proper implementation. Is an explicit JNDI lookup the proper way to do this?
Thanks,
Ryan -
7. Re: How to get EntityManager instance in a component marked @Startup
kapitanpetko Mar 30, 2010 3:19 AM (in response to purecharger)
Ryan N wrote on Mar 30, 2010 01:22:
I should have waited before posting. So obviously the instance I am instantiating and storing in the static Map is not managed by JBoss and will not have any interception or injection performed on it.Right, for injection to work you need to get SBs with @EJB or lookup from JNDI. For Seam components, you need to create them with @In(create=true) or use Component.getInstance().
My question now becomes: with EJB3 and JBoss what is corresponding Factory pattern? I'd like to continue to be able to use the CredentialsType enum to lookup the proper implementation. Is an explicit JNDI lookup the proper way to do this?Since your component is an SLSB it is already pooled by the container. So instead of caching those in a map, just return a fresh instance. If you decide to make it a Seam component, you can look it up by name. Something like:
public static CredentialsProcessor getProcessor(CredentialsType type) { swtich(type) { CSV: return Component.getInstance("csvProcessor", true); // or class: Component.getInstance(CSVCredentialsProcessor.class, true); XML: return Component.getInstance("xmlProcessor", true); default: // throw? }
If you stick with 'plain' EJB, use JNDI or inject all the processors you need if there is only a few.
Generally, you can safely make all your SBs Seam components (add @Name). That way you get the best of both worlds.
HTH
-
8. Re: How to get EntityManager instance in a component marked @Startup
purecharger Mar 30, 2010 11:51 PM (in response to purecharger)Thanks for your help!