Simple DataSource (Not XA) in persistence.xml - spring

If I am using "transaction-type" JTA in "persistence.xml" ,
then is it mandatory to use XA type data sources in "" element ?
or we can also using simple data source also .
Thanks !!

That depends. If you want to use JTA and have multiple participants (i.e. datasources, jms connections etc) then you really must have an XA capable datasource. When you don't have this you have problems starting a distributed transaction.
If this is the only participant ever then you might even wonder why do you want JTA transactions and stick with resource local transactions.

Related

Configuring transaction across multiple resources using spring framework?

I understand the fact that a transaction that spans multiple transactional resources is called a global transaction.
Question 1:
Is this just an another name for distributed transaction or is that something different?
Question 2:
Have gone through spring's documentation on Transaction Management.
What i could infer from that is
a. JTA is purely designed for distributed transactions.
b. Only through EJBs and EJB CMT, we could enforce distributed transactions.
c. If EJBs, then it mandates an Application Server and indirectly JNDI too.
What is Spring's counterpart to facilitate global/distributed transactions?
Question 3:
If we don't want to go with an application server with JTA capability,
should we be using Atomikos / JOTM like standalone Transaction managers to enforce global transactions?
Question 4:
A simple usecase of updating Table A in DB_1 (MySql) and Table B in DB_2 (Oracle) under a single transaction:
What is Spring's answer to this usecase?
Yes
a) No, not every transaction will be distributed, only if more than one resource is involved. The TM handles the management of the transactions executed on the involved resources
b) No, there are transactionsmanagers usable outside ejb-servers like atomikos, bitronix,... but I am not sure what you mean by enforce, as I wrote earlier, distributed transactions are used when necessary.
c) yes
d) Springs counterpart
if you want to use transactions on multiple resources at the same time yes.
you define two datasources in a way, that they let a TM handle their resources. Both MySql and Oracle provide XA-Datasources which allow it to handle distributed transactions. You define a TM and make it possible to annotate your beans with Transaction Attributes. There are many tutorials out there which show how this can be done.
Additional remarks:
Meanwhile transactions are also included in the CDI-Spec. So you can also use CDI.
Handle the distributed transactions wisely. The two way commit makes it almost impossible to set a reasonable transaction timeout. There are development-sites where distributed transactions only are used between one SQL-DBMS-Resource and one JMS-Resource if necessary.

How to do 2 phase commit between two micro-services(Spring-boot)?

I Have two mico-serives A and B where they connect to seperate database, From Mico-serives A i need to persist(save) objects of both A and B in same transtation how to achive this.
I am using Spring micro-servies with netflix-oss.Please give suggestions on best way to do achive 2 phase commit.
you can not implement traditional transaction system in micro-services in a distributed environment.
You should you Event Sourcing + CQRS technique and because they are atomic you will gain something like implementing transactions or 2PC in a monolithic system.
Other possible way is transaction-log-mining that I think linked-in is using this way but it has its own cons and pros. for e.g. binary log of different databases are different and event in same kind of database there are differences between different versions.
I suggest that you use Event Sourcing + CQRS and string events in an event-store then try reaching eventual consistency base on CAP theorem after transferring multiple events between micro-service A and B and updating domain states in each step.
It is suggested that you use a message broker like ActiveMQ, RabbitMQ or Kafka for sending event-sourced events between different microservices and string them in an event store like mysql or other systems.
Another benefit of this way beside mimicking transactions is that you will have a complete audit log.
It is an architecture(microservices) problem. Spring boot or netflix-oss do not offer a direct solution. You have to implement your own solution. Check with event driven architecture. It can give you some ideas.
You could try the SAGA pattern https://microservices.io/patterns/data/saga.html

Multiple DataSources, Multiple Transaction Managers. Which one is used?

I have a SI configuration that is made up of multiple data sources.
Say: DataSource A - Connects to Oracle
DataSource B - Connects to DB2
DataSource C - Connects to MySQL
One of the SI sub-flows writes to two of these data sources and I would like to do that in a 1-PC transaction.
So I define a ChainedTransactionManager with DataSource A and DataSource B. Let's call this chainedTransactionMgr
I also have two jdbc templates templateA(with A as it's datasource) and templateB (with B as it's datasource)
Let's say that I have a flow where I send a message to a publish-subscribe channel with two recipients that are service-activators that just use templateA and templateB to write the msg to their respective data source. Will the chained transaction manager be utilized in this flow?
Everything what you say is good and correct.
Only the problem that you have to do all the job in a single thread, because that is only the way how you can involve several resources to one transaction. Actually this is a case when you use publish-subscribe-channel with default configuration, where in the same thread first subscriber will call its templateA; and only after that the second service will call its templateB.
So, the ChainedTransactionManager should be configured with that order, too.
And from here it even doesn't matter if you use XA transaction manager. The main point is single thread.

Which method in BMP is used to avoid unnecessary round trips to the database?

If I'm using BMP bean, is there any method which avoids unnecessary roundtrips to database and increase the efficiency...
Does any of these method serve the purpose? (Question in a certification test)
ejbSave(), ejbStore() or ejbPersist()
In a multi-tiered architecture, with database, application server, and Web layers—you optimize performance by reducing the network traffic “round trip.” Best approach is said to be to start and stop transactions at the application server level, in the EJB container. So would like to know the methods help reduce unnecessary round-trips for that in Bean Managed persistence type beans....Am new to ejb.., so am trying to learn the concepts
ejbSave() and ejbpersist() do not exist...
You wouldn't have to deal with any of these methods: 'ejbSave(), ejbStore() or ejbPersist()'
If I'm using BMP bean, is there any method which avoids unnecessary roundtrips to database
Short Answer:
Yes, methods of EntityManager
Long Answer:
To avoid network round trips to the database, you'd just have to set the transaction boundaries correctly. When you use the methods provided by EntityManager (I'm talking about JPA), the methods act on the persistence context. The persistence context being a cache, real db hits are avoided until the commit happens.
Following is a section from the TomEE docs
JPA 101
If there's one thing you have to understand to successfully use JPA (Java
Persistence API) it's the concept of a Cache. Almost everything boils
down to the Cache at one point or another. Unfortunately the Cache is an
internal thing and not exposed via the JPA API classes, so it not easy to
touch or feel from a coding perspective.
Here's a quick cheat sheet of the JPA world:
A Cache is a copy of data, copy meaning pulled from but living
outside the database.
Flushing a Cache is the act of putting modified data back into the
database.
A PersistenceContext is essentially a Cache. It also tends to have
it's own non-shared database connection.
An EntityManager represents a PersistenceContext (and therefore a
Cache)
An EntityManagerFactory creates an EntityManager (and therefore a
PersistenceContext/Cache)
With you are
responsible for EntityManager (PersistenceContext/Cache) creating and
tracking...
-- You must use the EntityManagerFactory to get an EntityManager
-- The resulting EntityManager instance is a
PersistenceContext/Cache
-- An EntityManagerFactory can be injected via the #PersistenceUnit
annotation only (not #PersistenceContext)
-- You are not allowed to use #PersistenceContext to refer to a unit
of type RESOURCE_LOCAL
-- You must use the EntityTransaction API to begin/commit around
every call to your EntityManger
-- Calling entityManagerFactory.createEntityManager() twice results in
two separate EntityManager instances and therefor two separate
PersistenceContexts/Caches.
-- It is almost never a good idea to have more than one instance of
an EntityManager in use (don't create a second one unless you've destroyed
the first)
With the container
will do EntityManager (PersistenceContext/Cache) creating and tracking...
-- You cannot use the EntityManagerFactory to get an EntityManager
-- You can only get an EntityManager supplied by the container
-- An EntityManager can be injected via the #PersistenceContext
annotation only (not #PersistenceUnit)
-- You are not allowed to use #PersistenceUnit to refer to a unit of
type TRANSACTION
-- The EntityManager given by the container is a reference to the
PersistenceContext/Cache associated with a JTA Transaction.
-- If no JTA transaction is in progress, the EntityManager cannot be
used because there is no PersistenceContext/Cache.
-- Everyone with an EntityManager reference to the same unit in the
same transaction will automatically have a reference to the same
PersistenceContext/Cache
-- The PersistenceContext/Cache is flushed and cleared at JTA
commit time
Cache == PersistenceContext
The concept of a database cache is an extremely important concept to be
aware of. Without a copy of the data in memory (i.e. a cache) when you
call account.getBalance() the persistence provider would have to go read
the value from the database. Calling account.getBalance() several times
would cause several trips to the database. This would obviously be a big
waste of resources. The other side of having a cache is that when you call
account.setBalance(5000) it also doesn't hit the database (usually). When
the cache is "flushed" the data in it is sent to the database via as many
SQL updates, inserts and deletes as are required. That is the basics of
java persistence of any kind all wrapped in a nutshell. If you can
understand that, you're good to go in nearly any persistence technology
java has to offer.
Complications can arise when there is more than one
PersistenceContext/Cache relating the same data in the same transaction.
In any given transaction you want exactly one PersistenceContext/Cache for
a given set of data. Using a TRANSACTION unit with an EntityManager
created by the container will always guarantee that this is the case. With
a RESOURCE_LOCAL unit and an EntityManagerFactory you should create and use
exactly one EntityManager instance in your transaction to ensure there is
only one active PersistenceContext/Cache for the given set of data active
against the current transaction.

Spring Bean Hangs on Method with #Transactional

Just a little background , I'm a new developer who has recently taken over a major project after the senior developer left the company before I could develop a full understanding of how he structured this. I'll try to explain my issue the best I can.
This application creates several MessageListner threads to read objects from JMS queues. Once the object is received the data is manipulated based on some business logic and then mapped to a persistence object to be saved to an oracle database using a hibernate EntityManager.
Up until a few weeks ago there hasn't been any major issues with this configuration in the last year or so since I joined the project. But for one of the queues (the issue is isolated to this particular queue), the spring managed bean that processes the received object hangs at the method below. My debugging has led me to conclude that it has completed everything within the method but hangs upon completion. After weeks of trying to resolve this I'm at end of my rope with this issue. Any help with this would be greatly appreciated.
Since each MessageListner gets its own processor, this hanging method only affects the incoming data on one queue.
#Transactional(propagation = Propagation.REQUIRES_NEW , timeout = 180)
public void update(UserRelatedData userData, User user,Company company,...)
{
...
....
//business logic performed on user object
....
......
entityMgr.persist(user);
//business logic performed on userData object
...
....
entityMgr.persist(userData);
...
....
entityMgr.flush();
}
I inserted debug statements just to walk through the method and it completes everything including entityMgr.flush.().
REQUIRES_NEW may hang in test context because the transaction manager used in unit testing doesn't support nested transactions...
From the Javadoc of JpaTransactionManager:
* <p>This transaction manager supports nested transactions via JDBC 3.0 Savepoints.
* The {#link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
* to {#code false} though, since nested transactions will just apply to the JDBC
* Connection, not to the JPA EntityManager and its cached entity objects and related
* context. You can manually set the flag to {#code true} if you want to use nested
* transactions for JDBC access code which participates in JPA transactions (provided
* that your JDBC driver supports Savepoints). <i>Note that JPA itself does not support
* nested transactions! Hence, do not expect JPA access code to semantically
* participate in a nested transaction.</i>
So clearly if you don't call (#Java config) or set the equivalent flag in your XML config:
txManager.setNestedTransactionAllowed(true);
or if your driver doesn't support Savepoints, it's "normal" to get problem with REQUIRES_NEW...
(Some may prefer an exception "nested transactions not supported")
This kind of problems can show up when underlying database has locks from uncommitted changes.
What I would suspect is some other code made inserts/deletes on userData table(s) outside transaction or in a transaction which takes very long time to execute since it's a batch job or similar. You should analyze all the code referring to these tables and look for missing #Transactional.
Beside this answer, you may also check for the isolation level of your transaction — perhaps it's too restrictive.
Does the update() method hang forever, or does it throw an exception when the timeout elapses?
Unfortunately I have the same problem with Propagation.REQUIRES_NEW. Removing it resolves the problem. The debugger shows me that the commit method is hanging (invoked from #Transactional aspect implementation).
The problem appears only in the test spring context, when the application is deployed to the application server it works fine.

Resources