I cannot persist correctly when using multiple persist modules

975 views
Skip to first unread message

Vicente J. Ruiz Jurado

unread,
Mar 7, 2012, 8:17:26 AM3/7/12
to google...@googlegroups.com
Hi there:

(New post with more info)

I'm trying to use two databases in my project too. I was trying with:
http://code.google.com/p/google-guice/wiki/GuicePersistMultiModules
until I found this more complete snippet:
https://groups.google.com/d/topic/google-guice/2VK-bdsnjZc/discussion

Now I'm in a point where I can access to both databases (thanks scl) but, cannot persist nothing. I was trying to create several custom persist objects and annotations without luck.

Here is my package with the two modules http://ourproject.org/plugins/scmsvn/viewcvs.php/trunk/src/main/java/cc/kune/core/server/persist/?root=kune

Currently I'm trying to make my main persist module Private (so uncomment the expose, etc) here:,
http://ourproject.org/plugins/scmsvn/viewcvs.php/trunk/src/main/java/cc/kune/core/server/persist/DataSourceKunePersistModule.java?rev=1747&root=kune&view=auto
and I'm not using the second module (while I fix the persist issue).

but I'm get a NoResultException trying to get objects (if the module is Private) that normally are persisted and can be retrieved in other part of one transaction (if the module is Abstract).

(...)
Caused by: javax.persistence.NoResultException: No entity found for query
	at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:104)
	at
com.google.inject.persist.jpa.JpaFinderProxy.invoke(JpaFinderProxy.java:72)
	at
com.google.inject.persist.jpa.JpaPersistModule$1.invoke(JpaPersistModule.java:129)
	at $Proxy19.findByCode(Unknown Source)
	at
(...)

Also I was trying to use a custom @Transactional as scl suggested without luck. Here is my code:
http://ourproject.org/plugins/scmsvn/viewcvs.php/trunk/src/main/java/com/google/inject/persist/jpa/KuneJpaLocalTxnInterceptor.java?rev=1747&root=kune&view=auto

This gives me the same exception.

Any tip?

Bests,

Vicente

Vicente J. Ruiz Jurado

unread,
Mar 10, 2012, 1:37:49 AM3/10/12
to google...@googlegroups.com
No comments? It's not clear my explanation? Shall I provide more info?

Anyway as a summary: How to make @Transactional work with:
http://code.google.com/p/google-guice/wiki/GuicePersistMultiModules?
or even more simple, how to expose guice-persist stuff if is binded in a PrivateModule?

I'm blocked with this issue.

TIA,

Vicente

Alen Vrečko

unread,
Mar 11, 2012, 7:56:58 AM3/11/12
to google-guice
Don't have time to look into your problem. But here is a general
observation. In context of http://code.google.com/p/google-guice/wiki/GuicePersistMultiModules

If you have a DAO or any class for that matter that works on
persistenceUnitOne with @Transactional it MUST be bound in the private
module one. Example:

Module one = ...bind(UnitOneDao.class) ...expose(UnitOneDao.class)
Module two = ...bind(UnitTwoDao.class) ...expose(UnitTwoDao.class)

now Injector = createInjector(one,two)

UnitOneDao daoOne = injector.getInstance // @Transactional works
within the "private space" of persistenceUnitOne
UnitTwoDao daoTwo = injector.getInstance // @Transactional works
within the "private space" of persistenceUnitTwo

If your business logic never needs to write to both databases in the
same "transaction" then you have no problems. Just make sure you work
with private module space and expose the things.

If on the other hand you need to have ACID semantic on both databases
at the same time you need to go with JTA provider and custom
@Transactional.

You can expose the things as

Module one
= ...bind(UnitOneDao.class) ...expose(UnitOneDao.class) ...expose(EntityManager.class).annotatedWith(DatabaseOne.class);

then you can @Inject @DatabaseOne EntityManager

Cheers
Alen

On Mar 10, 7:37 am, "Vicente J. Ruiz Jurado" <vruiz.jur...@gmail.com>
wrote:

scl

unread,
Mar 12, 2012, 3:22:22 AM3/12/12
to google...@googlegroups.com
indeed your explanation is a little brief.
anayway I will look into your problem this evening (MET).

scl

unread,
Mar 12, 2012, 6:46:48 PM3/12/12
to google...@googlegroups.com
I checked out kune but didn't get it to compile correctly. So I looked into the code. Here are the 3 most obvious points I found:
If you need a more details then ask a more specific question :)

1) when you are using multiple data sources ALL your JpaPersistModules must be installed in a private module.

2) when you are binding a class within a private module it can use all bindings available in the public space as well as in the private space defined by the private module. Therefore it is not necessary to expose the EntityManager if you are only using it in classes which are binded within the private module and you don't need to annotate the injection points with @XxxDatasSource if you are binding the class within a private module. The other instances of EntityManager are not visible since they are binded in a different private module.
E.g.: don't expose the EntityManager from the DataSourceOpenfirePersistModule and don't annotate EntityManager with @DataSourceOpenfire in DataSourceOpenfireSessionProvider and OpenfireXmppRosterProvider
This will even allow you to reuse the same SessionProvider for all data sources since it does not contain any information about the data source. The configuration which data source is used is done implicitly by binding the SessionProvider in a private module which contains a JpaPersistModule.
You will have to expose the SessionProvider with an annotation if you want to be injected into a class which is binded outside the private module.
You will have to expose the finders which are binded in the private module. You don't have to expose them with an annotation if there are only available in one data source.

3) you cannot bind the transaction interceptor within your private module. This has to be done in the public space. The easiest way to do this is to add a getter to your private module which will return the interceptor. The Module who installs your private module can then obtain and bind the interceptor which is provided by the private module.
If you don't mind that a transactional method will open a transaction on ALL data sources you can use the default JpaLocalTxnInterceptor and the default @Transactional binding. If you want to control on which data sources a transaction is started you have to write your own TransactionInterceptor which is capable of handling a custome transactional annotation.

Vicente J. Ruiz Jurado

unread,
Mar 13, 2012, 8:11:38 AM3/13/12
to google...@googlegroups.com
Wow guys, thanks indeed for your detailed help. I'm trying your recommendations right now.

Bests,

Vicente

Vicente J. Ruiz Jurado

unread,
Mar 14, 2012, 7:22:47 AM3/14/12
to google...@googlegroups.com
3) you cannot bind the transaction interceptor within your private module.

Solved. 3) was the source of my problem...

This was stopping my work a lot ... so, thaaaaanks indeed....

Owen Berger

unread,
Mar 16, 2012, 10:25:09 PM3/16/12
to google...@googlegroups.com
I am having this same problem, but I am stuck at this...

"The Module who installs your private module can then obtain and bind the interceptor which is provided by the private module."

How do I do that?  I am currently providing the outside world with a getter from inside my custom transaction interceptor.  What would the code look like in my Uber-Module bind the interceptor on the parent level?

Thanks for any help.

scl

unread,
Mar 18, 2012, 9:50:44 AM3/18/12
to google...@googlegroups.com
class MyPrivateModuel extends Module {

   private MethodInterceptor interceptor;

   protected void configure() {
      // do some stuff
      interceptor = new MyInterceptor();
      requestInjection(interceptor);
   }

   public MethodInterceptor getInterceptor() {
      return interceptor;
   }
}

--------

class SomeModule extends AbstractModuel {

   protected void configure() {
      MyPrivateModuel pm = new MyPrivateModuel();
      install(pm);
     
      // here it comes
      bindInterceptor(any(), any(), pm.getInterceptor());
   }

   // more code
}

Michael Newton

unread,
May 16, 2012, 8:35:42 PM5/16/12
to google...@googlegroups.com

Reinhard Nägele

unread,
Oct 19, 2012, 2:44:13 AM10/19/12
to google...@googlegroups.com
Why do you use the injector directly in your examples? This defeats the whole point of DI. You should inject the DAOs instead.


Am Donnerstag, 18. Oktober 2012 20:12:28 UTC+2 schrieb पांडुरंग पाटिल:
I was also facing few issues while using Multiple Persistent units and was able to get it working.  refer this http://blog.pandurangpatil.com/2012/10/mulitple-persistence-unit-with-guice.html 

Thanks,
-Pandurang.

Dave Elton

unread,
Oct 19, 2012, 5:44:39 AM10/19/12
to google...@googlegroups.com
Reinhard is correct.

Your example is using Guice as a Service locator pattern rather than Dependency Injection. See: http://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte


Either Inject the DAOs (doing this via the constructor is my favourite as I can mark the Instance variables as final) :

public class PersonService { 

private final PersonDao personDao;
private final AddressDao addressDao;

@Inject 
public PersonService (PersonDao personDao, AddressDao addressDao){
  this.personDao = personDao;
  this.addressDao = addressDao;
}
}

You may also wish to inject providers (e.g. Provider<PersonDao>) if you want to defer instantiation of the DAOs until needed (e.g. the savePerson method). But to be honest, since PersonDao is a singleton, you may as well just keep it in the class and reuse it as required.

Dave Elton

--
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/-/Wc9zuuu3cKYJ.

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.

Reply all
Reply to author
Forward
0 new messages