I'm currently working on migrating GWT-RPC application to use RESTful services. For that, I repalced all RPC calls with domino-rest and additionally updated jersey1 to jersey2. Yes, jersey1 was already there for some external communication. Now, I have migrated all RPC calls to REST and at first I thought everything works great.
For dependcy injection I use Guice 6 and after migration to Jersey2 the HK2-Guice-bridge. For persistence of my multiple DBs I use JPA/Hibernate. Just for completeness: before starting the migration to Jersey2 and domino-rest everything was working.
Whenever I update a domain object to the database, that works perfect. But, when I request it again by a GET request I sometimes (!) receive an old version (from before the update) and sometimes the correct updated one. I checked the entire call stack and figured out, that it's no GET caching problem. The problem comes from my repository, more precise the EntityManager
, sometimes returns the old version.
The jersey2 log showed me, that different threads are used, so as the EntityManager
is not thread-safe I was thinking whether that's the problem. I'm not sure or is there anything else. If it's the thread-safe issue, it would be nice if you can help me what's wrong.
public class Repository<T> {
@Inject
private Provider<EntityManager> emProvider;
private final Class<T> entityType;
@Inject
public Repository(final Class<T> entityType) {
this.entityType = entityType;
}
public EntityManager getEntityManager() {
return emProvider.get();
}
public T get(long id) {
return getEntityManager().find(entityType, id);
}
public T update(T o) {
EntityManager em = getEntityManager();
em.merge(o);
em.flush();
return o;
}
//other code omitted
}
public class PersistenceModule extends PrivateModule {
private final String unitName;
public PersistenceModule(String unitName) {
this.unitName = unitName;
}
@Override
protected void configure() {
// I know setAutoBeginWorkOnEntityManagerCreation is not recommended, but for the time being.
install(new JpaPersistModule(unitName, JpaPersistOptions.builder().setAutoBeginWorkOnEntityManagerCreation(true).build()));
bind(PersistenceManager.class).asEagerSingleton();
expose(PersistenceManager.class);
// User
TypeLiteral<Repository<User>> userRepoType = new TypeLiteral<>() {
};
bind(userRepoType).toInstance(new Repository<>(User.class));
expose(userRepoType);
}
}
@Singleton
public class PersistenceManager {
private final PersistService service;
@Inject
public PersistenceManager(PersistService service) {
this.service = service;
service.start();
}
public void stop() {
service.stop();
}
}
My entry point for the web application is the ApplicationConfig
extending ResourceConfig
, where Guice.createInjector
with the above mentioned PersistenceModule
is called. The injector is then passed to the HK2-Guice Bridge. I hope you have a clue. Is there anything more required? Thank you!
Often it's a minor thing and in that case I missed to add filter("/*").through(PersistFilter.class);
to my Module extending ServletModule
. I use guice-persist
that's why PersistService
and PersistFilter
is in use and PersistFilter
starting the UnitOfWork
. Thank you both for your valuable input.