Hi all
I’m porting a
code
base that’s based on standard Java EE 6 with CDI, JSF2 etc over to a Vaadin UI. I’m a big fan of CDI, and even if I weren’t I’d be very reluctant to try to remove it from this codebase.
I’m using a custom CDI-enabled vaadin servlet, though I’m about to test the
CDI-Utils addon
after I found it earlier today. The servlet provides me with injection into the application and related classes, but doesn’t help with JPAContainer.
I’m trialling JPAContainer to use our existing mappings and entities with Vaadin. The app currently
@Provides EntityManager
instances using CDI alternatives to switch between different data sources and configurations for production vs test. More importantly, other parts of the app work with these entity managers - I don’t want a separate
EntityManagerFactory
just for Vaadin JPAContainer with its own separate pool of entities; the state of entities in the rest of the app should be reflected in JPAContainer. Creating a Vaadin specific
EntityManagerFactory
will also prevent injection into JPA2
EntityListener
from working once that comes out in JPA 2.2 (yay!) and waste resources on duplicate entities, mappings, etc.
So: ideally I’d like to continue to fetch our entity managers from CDI for JPAContainer. The Vaadin JPAContainer
com.vaadin.addon.jpacontainer.EntityProvider
interface doesn’t have a plug-in factory for
EntityManager
, but you can override it and provide your own
getEntityManager
impl so I’m hoping I can just subclass it, add an
@Inject EntityManager
member, have
getEntityManager
return that and have
setEntityManager
throw. If I then
@Inject
my factory subclass it should be enriched properly.
EDIT: Because a Class instance for the entity type is required, it’s better to use the EntityProvider implementation from vaadin unchanged, and supply an injected EntityManager from your Container subclass, as per the code at the end.
My main concern with this approach is that the JPAContainer documentation doesn’t say anything about whether it wants an extended or standard persistence context, what the transaction lifetimes are, etc. There’s some info in the EntityProvider subclasses, but it’s still quite limited. It’s hard to know how to design the app to interact with the container when its use of the EntityManager is somewhat opaque. I’m going to pull the sources (yay for sources!) but am hoping for an experienced opinion too.
I’ll test the simplistic approach now and see how it works. Opinions and suggestions welcome. Here’s how I’m hoping it can work:
Given some imaginary entity Customer, this might work but hasn’t been tested yet:
public class CustomerContainer extends JPAContainer<Customer> {
private static final long serialVersionUID = 1L;
@Inject
private EntityManager em;
public CustomerContainer() {
super(Customer.class);
}
@PostConstruct
protected void init() {
if (em == null) {
throw new IllegalStateException("EntityManager not injected");
}
LocalEntityProvider<Customer> provider = new LocalEntityProvider<>(Customer.class, em);
setEntityProvider(provider);
}
}