2017-09-10 3 views
0

Je voudrais écrire ma prochaine webapp Java en utilisant l'un des micro-cadres. Par exemple. Spark ou Jooby. Le problème est que les deux ne supportent pas JTA, donc j'ai besoin d'utiliser une des bibliothèques tierces. J'ai googlé pour les implémentations JTA open-source et en ai trouvé deux: Atomikos et Bitronix. Il semble que ce dernier projet soit légèrement abandonné alors j'ai décidé d'aller avec Atomikos. Malheureusement, la documentation est rare, donc je ne trouve pas de réponses à mes questions.Comment utiliser correctement TransactionManager autonome dans une application Web?

Voici le cas d'utilisation. Supposons que nous ayons deux classes DAO quelles méthodes doivent être exécutées sous transaction unique:

class SomeService { 

    // both injected by Guice 
    private FooDao fooDao; 
    private BarDao barDao; 

    public void someMethod() { 
     // both methods should be executed in a single transaction 
     fooDao.insert(new Foo()); 
     barDao.insert(new Bar()); 
    } 
} 

Je n'ai jamais utilisé javax.transaction API directement/manuellement avant (vous savez les transactions déclaratives sont très simples avec le printemps), donc je suis un peu confus. JTA fournit deux abstractions générales (UserTransaction et TransactionManager) et ils ont tous les deux des méthodes pour gérer la transaction JDBC. Autant que je comprenne TransactionManager exploite des objets UserTransaction en utilisant des variables ThreadLocal. Par conséquent UserTransaction doit être confiné au thread et TransactionManager supposé être thread-safe. Ai-je raison?

Donc il y a plusieurs approches possibles:

  1. Je peux injecter TransactionManager dans mon service (via Guice) et l'utiliser directement.
  2. Je peux partager TransactionManager via une variable statique publique.
  3. Je peux créer un fournisseur/une fabrique UserTransaction (via Guice) et en obtenir des objets.

Quelle est la bonne/meilleure pratique? Une autre question si quelqu'un connaissant Atomikos est qu'il fournit deux implémentations de gestionnaire de transactions (peut-être même plus): J2eeTransactionManager et UserTransactionManager. Encore une fois, la documentation est trop rare, donc je ne vois aucune différence sauf JNDI. Je suppose que UserTransactionManager devrait être suffisant pour mes besoins, mais les états de description qui suit

J2eeTransactionManager

Une mise en œuvre de TransactionManager qui devrait être utilisé par des applications J2EE .

.. sans aucune explication.

ps. Désolé mon anglais n'est pas bien je le sais.

+0

De quel type de ressources de transaction envisagez-vous d'utiliser? Bases de données SQL simples JMS-Files d'attente/Sujets? Est-ce que JPA est impliqué, quel ORM hiberne ou eclipselink? Avez-vous l'intention d'utiliser des transactions distribuées? Voulez-vous être capable d'annoter des classes ou des méthodes avec des attributs de transaction ou les transactions «gérées par le bean» sont-elles suffisantes? – aschoerk

+0

@aschoerk Tout ce dont j'ai besoin est d'exécuter deux méthodes à partir de classes DAO séparées en une seule transaction. J'utilise simple JDBC simple - pas de transactions JMS, JPA, XA ou d'autres choses JEE impliqués. J'utilise DI, cependant. Pour l'instant je veux juste comprendre comment partager correctement l'instance de TM ou UserTransaction. La gestion déclarative des transactions n'est pas nécessaire. Je suppose que, dès que je comprendrai comment utiliser TM, il sera assez simple d'écrire des transactions déclaratives personnalisées via un proxy de réflexion. – Evan

+0

Pourquoi ne pas partager la connexion JDBC? Je pense que cela devrait être suffisant pour vous. Juste simple "BEGIN TRANSACTION" et "COMMIT TRANSACTION" peuvent être utilisés autour de vos appels dao, si ceux-ci utilisent la même connexion. C'est tout, que votre MT ferait pour vous dans ces circonstances. – aschoerk

Répondre

0

Ок, puisque personne ne m'a répondu, après avoir creusé dans le code source, je pense que je suis prêt à répondre à ma propre question:

  1. Les deux Atomikos et Bitronix TMs mis en œuvre comme singletons [1], [2]
  2. Atomikos et Bitronix TM sont compatibles avec les threads. En particulier, Atomikos utilise la synchronisation intrinsèque et Bitronix ne partage pas l'état entre les threads.
  3. Les deux Atomikos et Bitronix TM implémenter les deux interfaces (oops) TransactionManager et UserTransaction de façon à ce que, fondamentalement, peu importe celle que vous utiliserez. Même si vous regardez la classe Atomikos UserTransactionImp, vous verrez qu'elle instancie et utilise en interne l'implémentation correspondante de TransactionManager.

Ainsi, il est possible d'avoir une seule instance TM-per-webapp, que vous pouvez partager comme vous le souhaitez. Depuis Atomikos TM supposed to be instantiated il est préférable de le partager via l'injection de dépendance. Bitronix TM peut être utilisé par public static method comme n'importe quel autre singleton.

De plus, vous pouvez gérer les transactions via JNDI. Vous pouvez trouver un exemple dans le code source Java Persistence avec Hibernate.

+0

Je suis simplement curieux, comment ces solutions garantissent-elles que vos instructions JDBC sont réellement exécutées dans les contextes de transactions que vous définissez en appelant begin et commit? Est-ce que votre implémentation JDBC trouve également ces TM et s'enregistre-t-elle (d'accord, cela semble être la solution atomique que vous utilisez)? Configurez-vous les mémoires de traduction afin qu'elles synchronisent les connexions JDBC? – aschoerk

+1

@aschoerk Chaque MT fonctionne uniquement avec l'implémentation javax.sql.DataSource du même fournisseur. Par exemple, Atomikos TM doit utiliser soitAtomikosNonXADataSourceBean soit AtomikosXADataSourceBean. Bitronix TM doit utiliser PoolingDataSource de Bitronix et ainsi de suite. Lorsque vous utilisez Spring, vous pouvez réellement utiliser une implémentation de source de données arbitraire en la transmettant à DataSourceTransactionManager, mais lorsque vous utilisez l'une des MT mentionnées ci-dessus, ce n'est pas un accord. – Evan

+0

La manière dont ils partagent l'état de connexion est spécifique au fournisseur. Je n'ai pas creusé si profond. Mais si vous regardez la [implémentation TM] beaucoup plus simple (https://github.com/odnoklassniki/one-datasource/blob/master/src/one/datasource/DataSourceImpl.java#L261), vous verrez qu'il peut travailler via JNDI. – Evan