Reputation: 7011
I'm using Guice to Inject EntityManager. When I commit the trasaction of the injected entityManager there is nothing happend in the BD side : no transaction passed !!! can you help me to figure out what is going on ?
Here is my code :
Web.xml
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>ca.products.services.InjectorListener</listener-class>
</listener>
The InjectorListener class :
public class InjectorListener extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
return Guice.createInjector(
new PersistenceModule(),
new GuiceModule(),
new RestModule());
}
}
The persistenceModule class :
public class PersistenceModule implements Module {
@Override
public void configure(Binder binder) {
binder
.install(new JpaPersistModule("manager1")
.properties(getPersistenceProperties()));
binder.bind(PersistenceInitializer.class).asEagerSingleton();
}
private static Properties getPersistenceProperties() {
Properties properties = new Properties();
properties.put("hibernate.connection.driver_class", "org.postgresql.Driver");
properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/postgres");
properties.put("hibernate.connection.username", "postgres");
properties.put("hibernate.connection.password", "postgres");
properties.put("hibernate.connection.pool_size", "1");
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.hbm2ddl.auto", "create");
return properties;
}
}
The GuiceModule class :
public class GuiceModule extends AbstractModule {
@Override
protected void configure() {
bind(MemberRepository.class).to(MemberRepositoryImp.class);
bind(ProductRepository.class).to(ProductRepositoryImpl.class);
bind(ShoppingBagRepository.class).to(ShoppingBagRepositoryImpl.class);
}
}
The RestModule class :
public class RestModule extends JerseyServletModule {
@Override
protected void configureServlets() {
HashMap<String, String> params = new HashMap<>();
params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "ca.products.services");
params.put(JSONConfiguration.FEATURE_POJO_MAPPING, "true");
params.put(ResourceConfig.FEATURE_DISABLE_WADL, "true");
serve("/*").with(GuiceContainer.class, params);
}
}
and Finally the webservice (jeresy) call:
@Inject
private Provider<EntityManager> em;
@GET
@Transactional
@Path("/reset")
public void resetData() {
logger.info("Processing reset");
try {
em.get().getTransaction().begin();
for (int i = 0; i < 10; i++) {
em.get().persist(new Product("Product_" + i, "Desc_" + i));
}
em.get().flush();
em.get().getTransaction().commit();
} catch (Exception e) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
}
Upvotes: 0
Views: 836
Reputation: 7255
You probably need to add the a persist filter. This will also keep you from having to manage transactions manually. If you do not use the filter you can still inject the UnitOfWork to create transactions. If you are using jpa persist you should not be managing userTransactions.
This is a custom filter that also adds a Lifecycle which it automatically started on startup with some custom code and a map binder builder. It is only there for thoroughness. It is not part of the guice api but more similar to spring's Lifecycle listener. I don't have any spring dependencies at all.
@Singleton
public final class JpaPersistFilter implements Filter {
private final UnitOfWork unitOfWork;
private final PersistServiceLifecycle persistService;
@Inject
public JpaPersistFilter(UnitOfWork unitOfWork, PersistServiceLifecycle persistService) {
this.unitOfWork = unitOfWork;
this.persistService = persistService;
}
public void init(FilterConfig filterConfig) throws ServletException {
// persistService.start();
}
public void destroy() {
persistService.stop();
}
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
final FilterChain filterChain) throws IOException, ServletException {
unitOfWork.begin();
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
unitOfWork.end();
}
}
/**
* Extra lifecycle handler for starting and stopping the service. This
* allows us to register a {@link Lifecycle} with the
* {@link LifecycleListener} and not have to worry about the service being
* started twice.
*
* @author chinshaw
*
*/
@Singleton
public static class PersistServiceLifecycle implements Lifecycle {
private final PersistService persistService;
private volatile boolean isStarted = false;
@Inject
public PersistServiceLifecycle(PersistService persistSerivce) {
this.persistService = persistSerivce;
}
@Override
public boolean isRunning() {
return isStarted;
}
@Override
public void start() {
if (!isStarted) {
persistService.start();
isStarted = true;
}
}
@Override
public void stop() {
persistService.stop();
isStarted = false;
}
}
}
Example of adding filter to module.
@Override
protected void configureServlets() {
filter("/api/*").through(JpaPersistFilter.class);
}
Example of using unit of work to manage the transaction.
@Inject
UnitOfWork unitOfWork;
public void doSomething() {
unitOfWork.begin();
try {
dao.saveState(someobject);
} finally {
unitOfWork.end();
}
}
Upvotes: 1