Re: guice-persist and JPA: working with multiple EntityManagerFactory instances based on same persistence-unit

1,045 views
Skip to first unread message

Stephan Classen

unread,
Sep 26, 2012, 9:15:49 AM9/26/12
to google...@googlegroups.com, Martin Schayna
Ok

I'm not sure I understand completely what you need. But here is my first
proposal:
Write your own PersistFilter (see below) and use
EntityManager.setProperty to set the request specific properties.

@Singleton
public final class MyPersistFilter implements Filter {
private final UnitOfWork unitOfWork;
private final Provider<EntityManager> emProvider;
private final PersistService persistService;

@Inject
public PersistFilter(UnitOfWork unitOfWork, Provider<EntityManager>
emProvider, PersistService persistService) {
this.unitOfWork = unitOfWork;
this.emProvider = emProvider;
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 {
final EntityManager em = emProvider.get();
final Map<String, String> props =
getPropertiesForRequest(servletRequest);
for(String key: props.keySet()) {
em.setProperty(key, props.get(key));
}
filterChain.doFilter(servletRequest, servletResponse);
} finally {
unitOfWork.end();
}
}

private Map<String, String> getPropertiesForRequest(final
ServletRequest servletRequest) {
// TODO
return null;
}
}

Stephan Classen

unread,
Sep 28, 2012, 7:58:37 AM9/28/12
to google...@googlegroups.com
Its possible but its way more complicated.
In Fact the Provider<EntityManager>, UnitOfWork and PersistService are all implemented in the single class JpaPersistService.
And the JpaPersistService has a static inner class which is the Provider<EntityManagerFactory> which it uses directly and not over injection.

This implementation couples all the above interfaces so tightly that I don't see a way to get in between them.
This means you would have to rewrite all of them.

It is not that hard to do. My opinion is that you would need two classes:
- one which implements PersistService and Provider<EntityManagerFactory>
- one which implements UnitOfWork and Provider<EntityManager>
Most of the code can be copied from the JpaPersistService.

And finally you would have to write you own XxxPersistModule which binds the above classes.

Since creating an EntityManagerFactory is expensive it might be worth storing the created ones in a map for later reuse.



On 09/27/2012 10:01 AM, Martin Schayna wrote:
Thanks a lot. In my case I have to parametrize creation of EntityManagerFactory, not EntityManager, because each request may work with different database. Persistence unit defined in persistence.xml is the same one, but properties like hibernate.connection.url are passed to Persistence.createEntityManagerFactory("persistence-unit", myProperties).

Can I use my own Provider<EntityManager> implementation and bind it to EntityManager interface, instead of default implementation in guice-persist?
--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/BRd0U6Urq94J.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Daniel Bimschas

unread,
Jun 24, 2013, 4:14:51 PM6/24/13
to google...@googlegroups.com
Hi,

I've just discovered this thread and I find myself in a somewhat similar situation as described by Martin, working with guice-persist. In my case I have a POJO holding the applications configuration which gets injected itself from bound constants loaded from a properties file. So (from my understanding) at the time of installing the guice-persist module, the POJO instance can't be created/injected yet as we're still in the phase of configuring the bindings, so I can't access the POJOs fields to load the properties for the guice-persist module.

I've also discovered https://github.com/sclassen/guice-jpa which looks like its able to solve one of my other issues but I couldn't figure out how to solve this runtime configuration issue with it either.

Any ideas?

Cheers,
Daniel


On Wednesday, 26 September 2012 10:11:08 UTC+2, Martin Schayna wrote:
Hi,

I have small API server application based on Jersey, Hibernate/JPA and Guice, running in Tomcat. I want to use guice-persist extension for better handling EntityManager instances and transactions. Now I'm doing the whole work in each controller method, so each method creates EntityManager, starts transaction, close everything etc. The guice-persist thing looks pretty straightforward, but I don't know how to handle this:

I have only one persistence-unit, but application caches more EntityManagerFactory instances, each with its own properties. These properties are loaded from configuration on runtime. I cannot configure GuiceServletContextListener with module JpaPersistModule("unit").properties(myProperties) because myProperties are based on request parameters -- my application supports multi-tenancy and tenants has data in several similar databases.

How can I use guice-persist with this scenario?

Thanks, 
Martin Schayna

Stephan Classen

unread,
Jun 25, 2013, 3:04:31 AM6/25/13
to google...@googlegroups.com
Hi

You are right, neither guice-persist nor guice-jpa provide the option to inject the persistence unit name.
This is because it is kind of a chicken egg problem.

In order to inject the persistence unit name you need an injector, then on the other hand you can't have the injector before configuring the modules...
I guess you could build a persistence extension which instead of taking the name in the constructor just requires a binding with a given name to be defined (I may consider this for a next release of gucie-jpa).

But for now it is not easily doable. What I usually do is collect all the information needed to configure the injector in a single property file. And then do it the "old Java" way, load that one file using java.util.Properties and java.lang.ClassLoader.getResourceAsStream(String).
I like this because the settings for configuring guice are separated from the rest and are all in a single place. In most projects I have not more than 3 settings in this properties file.

Hope this helps
--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.

To post to this group, send email to google...@googlegroups.com.

Laszlo Ferenczi

unread,
Jun 25, 2013, 3:42:29 AM6/25/13
to google...@googlegroups.com
Hi,

How about creating a "preloader" injector - only containing the configuration - and calling injectMembers() on the actual module classes ?

        Injector modulesInjector = Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
            @Override
            protected void configure() {
                Names.bindProperties(binder(), p);   // p holds all the properties
            }
        });
for (AbstractModule module : all) {
            modulesInjector.injectMembers(module);
}
        Injector injector = Guice.createInjector(Stage.PRODUCTION, all);

Is this considered an anti-pattern ?

--
L

--
L
Reply all
Reply to author
Forward
0 new messages