Exception thrown when using non-XA datasource in two-phase commit transaction - java

My Websphere application has 3 datsources. Two of them are XA and the other is non-XA.
I have made a Java method transactional by annotating the method with #transactional annotation.
Within the method, 3 tasks are performed. The first one is using one XA datasource to do some update, then the second one uses the non-XA datasource to select a few records and the final task uses another XA datasource to do some update again.
However, an exception is thrown with the following error:
An illegal attempt to commit a one phase capable resource with existing two phase capable resources
I want to know why the above error occurs even my application just uses the non-XA to select some data and no commit is required and how I can get rid of the problem if I am not allowed to change the non-XA datasource to XA.

The non-XA resource cannot by default participate in a distributed transaction. So you have the following options:
Change datasource to XA - you wrote that you cannot do that
Try to enable Last Participant Support - Last participant support is an extension to the transaction service that enables a single one-phase resource to participate in a two-phase transaction with one or more two-phase resources.
Set this (nonXA) datasource to be non transactional, if you don't need transactions for it. It will not be enlisted in the transaction:
Select Resources > JDBC > Data sources
Select the name of the data source that you want to configure.
Select WebSphere Application Server data source properties from the Additional Properties heading.
Select Non-transactional data source.
Click OK.
wrap that nonXA call in EJB, and mark it as not supporting transactions.
Manually manage transaction - don't use container managed transaction, but handle transaction inside your method manually using Transaction API.

when starting the second task, the previous task which does updates on a XA datasource need to be commit or rolled back while you are using #Transaction annotation the whole tasks automatically go through one transaction so don't use #Transaction annotation and instead of it put each task inside separate transaction

Related

When to Use XA Datasource and Non XA Datasource

I'm trying to understand the use of Java XA Datasource.
But I can't still figure when to use it, and when not to use it.
I read that XA Datasource used when we use two databases.
But I'm not sure what is the meaning of two database.
For example:
I had two layer of classes (Service and DAO)
A method in service layer annotated as a transaction, invoke two methods in DAO.
Each method in DAO open new connection to database and close it in the end of the method.
If I use one instance of database, and each method in DAO write to different table, do I have to use XA Datasource? since transaction occured in service layer but only in one instance database
Systems such as databases, but also for example queueing systems that you use through JMS have the concept of transactions. A transaction is treated as a unit of work; at the end of doing the work, such as inserting, updating or deleting records in the database, you commit the transaction and then the database definitively does the work; or you rollback the transaction and then everything done in the transaction is cancelled.
In some cases, your software has to perform operations over multiple different systems. For example, you might need to insert data into multiple databases, or insert something in the database and put a message on a queue.
If you want to do such combinations of operations as if they are in one transaction, then you need a distributed transaction system - a system that can combine the transactions of the different systems into one. That way you can write your code as if it's running inside a single transaction; the distributed transaction system automatically commits or rolls back the transactions in the underlying systems.
To make it more concrete: Suppose that you insert a record in a database, and put a message on a queue, and you want to do this inside one transaction. When something goes wrong with putting the message on the queue, you also want the database transaction to be rolled back, so that you don't have a record in the database but not a corresponding message on the queue. Instead of manually keeping track of the transactions of the database and the queue system (including handling all combinations of possible errors), you can use a distributed transaction system.
XA is a standard for working with distributed transactions. You can work with XA transactions in Java through the Java Transaction API (JTA). Java EE servers have support for this built-in. If you're not using a Java EE server, then you can use a separate library that implements JTA such as Narayana or Atomikos.
Each method in DAO open new connection to database and close it in the end of the method.
Normally this isn't how you should write DAOs. Opening a database connection is a relatively slow operation; if you open a new database connection for every method that you call in a DAO, your program is most like going to run slowly. You should at least use a connection pool, that manages a number of database connections and allows you to reuse already open connections.
If I use one instance of database, and each method in DAO write to different table, do I have to use XA Datasource? since transaction occured in service layer but only in one instance database
If your DAO methods each open their own connection, then they will run in separate transactions. Whether this is a problem or not depends on what your application needs to do. An XA datasource is not the solution to make them run in one transaction. Instead, you should both let them use the same connection and transaction.
XA transactions are really only useful if you are using multiple database systems or other systems, and you want to be able to perform transactions that span across these systems.

Is there a way to force Hibernate to use new connection for next transaction within a Spring application?

In Spring applications (that use Spring's declarative transaction management) when using JPA/Hibernate, when a transaction is first started within a request, Hibernate session is created and a database connection will be obtained from a datasource in order to execute this first transaction. Any subsequent transaction within the request will reuse the session and the connection. Is there a way to force Hibernate (or Spring's transaction management system) to obtain a new connection from the datasource for the subsequent transaction?
Background info and what I am trying to achieve
I'm using a custom implementation of AbstractRoutingDatasource to route database requests between a master and a replicated slave (read-only) database. I've created custom annotation with datasource routing information and AOP Aspect that intercepts the methods annotated with my custom annotation in order create a framework where one could add additional datasource routing annotation in addition to #Transactional in order to select a datasource (master or slave) on which the transaction should be executed. Aspect informs the routing datasource that next connection requested within current thread should go to a specific datasource (as defined in the annotation) before transaction starts. The problem is this only works on the first transaction because Hibernate caches connection and does not request new one for next transaction.
You will need to implement a custom ConnectionProvider. Hibernate will by default come with DriverManagerConnectionProviderImpl. However, most people end up using c3p0 (many without even knowing it), proxool, Hikari, or some other implementation.
All of these (including Hibernate's default) will cache connections (it is their primary purpose). You will probably need to create a connection provider which has a reference to two other connection providers (one per data source). The inner connection providers can be c3p0 or whatever other implementation you want to use.
This article gives a good basic overview of the concept (as well as describing what property to set to supply your own).

XA transaction for two phase commit

hi,
If two resources are involved in a transaction then the XA transation
setting should be enabled in the weblogic server. Then the xa drivers
has to be chosed.Is there a alternative way to have this two
resources in a transaction without enabling XA transaction
Yes, you can use Global Transaction Emulation. WebLogic has two mode:
Logging Last Resource - WebLogic creates a table into all your datasources and write transactions data into this table. This is a preference option.
From official documentation:
With this option, the transaction branch in which the connection is used is processed as the >last resource in the transaction and is processed as a local transaction. Commit records for >two-phase commit (2PC) transactions are inserted in a table on the resource itself, and the >result determines the success or failure of the prepare phase of the global transaction. >This option offers some performance benefits and greater data safety than Emulate Two-Phase >Commit, but it has some limitations.
see http://docs.oracle.com/cd/E15051_01/wls/docs103/jta/llr.html
Emulate Two-Phase Commit - transaction branch always return "SUCCESS" while prepare phase. Select this option if your app can tolerant heuristic conditions.
see http://docs.oracle.com/cd/E23943_01/web.1111/e13737/transactions.htm for more information.
I prefer LLR option, but if you work with legacy DB and do not have the table create grant, you should use two-phase commit emulation.

can you create your own JTA transaction?

I am loading a large set of data into a database from a webservice. I am using eclipslink for persistence and running the application on glassfish 3.0. I run into problems on my test data set in that there are a few foreign key constraint violations. I am fine with the violation, I do not want that data if it is not complete. My problem however comes in that the exception is thrown in the container. That then marks my transaction for a rollback, and I get no data at all then.
I would like to continue using JTA but am not sure if I can do what I want to achieve, and that is create my own JTA transaction so I can control when it commits,etc. I am not sure if that is a good idea though as I feel by doing so I may be destroying some of the benefits of using JTA.
So is it possible to get a JTA transaction?
Do the database work in a method of a session bean. Annotate that method with:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
It will be given its own transaction. The outer transaction will be suspended while it does its stuff.
http://wiki.eclipse.org/Using_Advanced_Unit_of_Work_API_%28ELUG%29#Integrating_the_Unit_of_Work_with_an_External_Transaction_Servicestrong text**
Read How to Acquire a Unit of Work with an External Transaction Service. Apparently you can snatch the UserTransaction and/or start your own by querying the container JNDI for UserTransaction

how the Transaction concept is implemented in EJB

I wan to know how the transaction is internally implemented in EJB. I want to know the logic they use to create a transaction. if you could point out some articles that would be helpful
Hibernate doesn't implement transactions, it relies on and wraps JDBC transactions or JTA transactions (either container managed or application managed).
Regarding EJBs, if you want to understand the details of a JTA Transaction Manager, you'll need to be fluent with the JTA interfaces UserTransaction, TransactionManager, and XAResource which are described in the JTA specification. The JDBC API Tutorial and Reference, Third Edition will also be useful to understand the XA part of a JDBC driver.
Then, get the sources of an EJB container (like JBoss) or of a standalone JTA Transaction Manager (like Atomikos) to analyze the TM part. And good luck.
This question could have answers at many levels.
A general discussion of what's going on can be found here
My summary goes like this ... First, somewhere there must be a transaction coordinator, the EJB container will know about the coordinator - typically that's part of the application server. So all the EJB container has to do is to call
someobject.BeginTransaction()
that's it. The actual API the EJB container uses is JTA. EJBs can actually use Bean Managed transaction transaction or Container managed transactions. In the Bean Managed case the implementer nhas to make the JTA calls. More usually we use Container Managed transactions (CMT). In which case the container has logic which is run before the implementation is reached. For example:
if ( we're not already in a transaction )
begin transaction
call the EJB implementation
and later the container has logic
if ( finished processing request )
commit transaction
with other paths to abort the transaction if errors have happened.
Now that logic is more complex because CMT EJBs are annotated with transaction control statements. For example you can say things "if we already have a transaction, use it" So if one EJB calls another only a single transaction is used. Read up the EJB spec for that.
However all that's pretty obvious in any write-up of Java EE EJBs. So I suspect that you're asking moe about what happens inside the JTA calls, how the transaction manager is implemented and its relationship to the transactional resource managers (eg. Databases). That's a huge topic. You've actually go implementations of the XA distributed transaction protocol down there. Frankly I doubt that you really need to need to know this. At some point you have trust the APIs you're using. However there is one key detail: your Transaction Manager (typically the App Server itself) must be able to tell the REsource Managers the fate of any given transaction, and that information must survive restart of the App Server, hence some persistent store of transaction information must be kept. You will find transaction logs somewhere, and in setting up the App Server you need to make sure those logs are well looked after.
From EJB in Action book
The protocol commonly used to achieve multiple resource is the two-phase commit. The two-phase commit protocol performs an additional preparatory step before the final commit. Each resource manager involved is asked if the current transaction can be successfully committed. If any of the resource managers indicate that the transaction cannot be committed if attempted, the entire transaction is abandoned (rolled back). Otherwise, the transaction is allowed to proceed and all resource managers are asked to commit.
A resource manager can be a database, for instance. Others examples includes a Message Service. The component which coordinates transactions is called Transaction manager.
Suppose you have an application which involves two distincts databases. How does Transaction manager performs its work by using Two phase commit protocol ?
Transaction Manager ask database 1 if it can commit the current transaction
If so, ask database 2 if it can commit the current transaction
Transaction Manager ask database 1 to commit
Transaction Manager ask database 2 to commit
Hibernate is built on top of the JDBC API. It just coordinates one database. So if you call
session.commit();
Behind the scenes, it call
connection.commit();
If you really want to study Transaction internals, my advice is Java Transaction Processing book.
Hibernate has TransactionFactory:
An abstract factory for Transaction instances. Concrete implementations are specified by hibernate.transaction.factory_class.
It has implementations: JDBCTransactionFactory, JTATransactionFactory, CMTTransactionFactory. These factories create an instance of Transaction - for example JDBCTransaction.
Then I can't tell you what happens for JTA and CMT, but for JDBC it's as simple as setting the auto-commit to false (when you call begin a transaction):
connection.setAutoCommit(false);
And respectively on transaction.commit(): connection.commit()
If any exception occurs when operating with the session, it invokes connection.rollback()
Another good read would be the JTS articles by Brian Goetz; links:
http://www.ibm.com/developerworks/java/library/j-jtp0305.html
http://www.ibm.com/developerworks/java/library/j-jtp0410/index.html
http://www.ibm.com/developerworks/java/library/j-jtp0514.html

Categories

Resources