I'm trying to wrap my head around the value underneath the Java Transactions API (JTA) and one of its implementations, Bitronix. But as I dig deeper and deeper into the documentation, I just can't help but think of the following, simple example:
public interface Transactional {
public void commit(Object);
public void rollback();
}
public class TransactionalFileWriter extends FileWriter implements Transactional {
#Override
public void commit(Object obj) {
String str = (String)obj;
// Write the String to a file.
write(str);
}
#Override
public void rollback() {
// Obtain a handler to the File we are writing to, and delete the file.
// This returns the file system to the state it was in before we created a file and started writing to it.
File f = getFile();
// This is just pseudo-code for the sake of this example.
File.delete(f);
}
}
// Some method in a class somewhere...
public void doSomething(File someFile) {
TransactionalFileWriter txFileWriter = getTxFW(someFile);
try {
txFileWriter.commit("Create the file and write this message to it.");
} catch(Throwable t) {
txFileWriter.rollback();
}
}
Don't get too caught up in the actual code above. The idea is simple: a transactional file writer that creates a file and writes to it. It's rollback() method deletes the file, thus returning the file system to the same state it was in before the commit(Object).
Am I missing something here? Is this all the JTA offers? Or is there a whole different set of dimensionality/aspects to transactionality that isn't represented by my simple example above? I'm guessing the latter but have yet to see anything concrete in the JTA docs. If I am missing something, then what is it, and can someone show me concrete examples? I can see transactionality being a huge component of JDBC but would hopefully like to get an example of JTA in action with something other than databases.
As every one else has mentioned, the primary benefit of JTA is not the single transaction case, but the orchestration of multiple transactions.
Your "Transactional File" is an excellent, conceptual, example when used in the proper context.
Consider a contrived use case.
You're uploading a picture that has associate meta data and you want to then alert the infrastructure that the file as arrived.
This "simple" task is fraught with reliability issues.
For example, this workflow:
String pathName = saveUploadedFile(myFile);
saveMetaData(myFile.size(), myFile.type(), currentUser, pathName);
queueMessageToJMS(new FileArrivalEvent(user, pathName);
That bit of code involves the file system and 2 different servers (DB and JMS).
If the saveUploadedFile succeeds, but the saveMetaData does not, you now have a orphaned file on the file system, a "file leak" so to speak. If the saveMetaData succeeds, but the queue does not, you have saved the file, but "nobody knows about it". The success of the transaction relies upon all 3 components successfully performing their tasks.
Now, throw in JTA (not real code):
beginWork();
try {
String pathName = saveUploadedFile(myFile);
saveMetaData(myFile.size(), myFile.type(), currentUser, pathName);
queueMessageToJMS(new FileArrivalEvent(user, pathName);
} catch(Exception e) {
rollbackWork();
} finally {
commitWork();
}
Now it "all works", or "none of it works".
Normally folks jump through hoops to make this kind of thing work safely, since most systems do not have transaction managers. But with a transaction manager (i.e. JTA), you the TM manages all of the hoops for you, and you get to keep your code clean.
If you survey the industry you will find very few transaction managers. Originally they were proprietary programs used by "Enterprise" grade systems. TIBCO is a famous one, IBM has one, Microsoft has one. Tuxedo used to be popular.
But with Java, and JTA, and the ubiquitous Java EE (etc) servers "everyone" has a transaction manager. We in the Java world get this orchestration for "free". And it's handy to have.
Java EE made transaction managers ubiquitous, and transaction handling a background consideration. Java EE means "never having to write commit() again". (Obviously Spring offers similar facilities).
For most systems, it's not necessary. That's why most people don't know much about it, or simply don't miss it. Most systems populate a single database, or simply don't worry about the issues surrounding orchestration of multiple systems. The process can be lossy, they have built in their own clean up mechanisms, whatever.
But when you need it, it's very nice. Committing to multiple system simultaneously cleans up a lot of headaches.
The biggest feature of JTA is that you can compose several transactional stores in one application and run transactions that span across these independent stores.
For instance, you can have a DB, a distributed transactional key-value store and your simple FileWriter and have a transaction that performs operations on all of these and commit all the changes in all the stores at once.
Take a look at infinispan. That's a transactional data grid, it uses JTA and can be used in combination with other JTA transactional services.
Edit:
Basically JTA is connected to the X/Open XA standard and it provides means to interact with X/Open XA resources directly in Java code. You can use alredy existing data-stores which hold X/Open XA compliant resources, such as databases, distributed data-grids and so on. Or you can define your own resources by implementing javax.transaction.xa.XAResource. Then, when your User transaction uses these resources, the transaction manager will orchestrate everything for you, no matter where the resources are located, in which data-store.
The whole bussiness is managed by the transaction manager which is responsible for synchronizing independent data-stores. JTA doesn't come with a transaction manager. JTA is just an API. You could write your own if you wish to (javax.transaction.TransactionManager), but obviously that's a difficult task. Instead what you want is to use some already implemented JTA service/library which features a transaction manager. For instance, if you use infinispan in your application you can use its transaction manager to allow your transactions to interact with different data-stores as well. It's best to seek further information on how to accomplish this from the implementators of JTA interface.
You can find full JTA API documentation here, though it's pretty long. There are also some tutorials available that talk about how to use Java EE Transaction Manager and update multiple data-stores but it is pretty obscure and doesn't provide any code samples.
You can check out Infinispan's documentation and tutorials, though I can't see any example that would combine Infinispan with other data-store.
Edit 2:
To answer your question from the comment: your understanding is more or less correct, but I'll try to clarify it further.
It'll be easier to explain the architecture and answer your question with a picture. The below are taken from the JTA spec 1.1
This is the X/Open XA architecture:
Each data-store (a database, message queue, SAP ERP system, etc) has its own resource manager. In case of a relational database, the JDBC driver is a resource adapter that represents the Resource Manager of the database in Java. Each resource has to be available through the XAResource interface (so that Transaction Manager can manage them even without knowing the implementation details of a specific data-store).
Your application communicates with both the Resource Managers (to get access to the specific resources) by the resource adapters, as well with the Transaction Manager (to start/finish a transaction) by the UserTransaction interface. Each Resource Manager needs to be initialized first and it has to be configured for global transactions (i.e. spanning across several data-stores).
So basically, yes, data-stores are independent logical units that group some resources. They also exhibit interface that allows to perform local transactions (confined to that specific data-store). This interface might be better-performing or might expose some additional functionality specific to that data-store which is not available through the JTA interface.
This is the architecture of JTA environment:
The small half-circle represents the JTA interface. In your case you're mostly interested in the JTA UserTransaction interface. You could also use EJB (transactional beans) and the Application Server would manage transactions for you, but that's a different way to go.
From the transaction manager’s perspective, the actual implementation of the
transaction services does not need to be exposed; only high-level interfaces need to be
defined to allow transaction demarcation, resource enlistment, synchronization and
recovery process to be driven from the users of the transaction services.
So the Transaction Manager can be understood as an interface which only represents the actual mechanism used to manage transactions such as JTS implementation, but thinking about it as a whole is not an error neither.
From what I understand, if you run for instance a JBoss application server, you're already equipped with a Transaction Manager with the underlying transaction service implementation.
Related
We are currently using axon framework with hikaricp as data source pooling system. We are facing pool exhausting issues from time to time and we have a theory:
To update our read models we use the command bus to send UpdateEntityViewCommand.
As the command bus starts a transaction using the primary transaction manager (the write one) it acquires a connection from the write pool
On the handler, we open an inner transaction using a connection from the read pool, thus blocking the outer one.
This seems to exhaust the pools under some conditions. The question is: should we stop using the command bus to update our read models? Is appropiate to have two buses( one for write and one for read?
Thanks in advance
Axon's intent with the separation of Commands, Events, and Queries, is in general to support CQRS within your system. This means you would introduce dedicated Command Models and Query Models, which respectively only receive Command and Query messages.
The Query Models are typically also referred to as Projections or Read Models.
It is this combination of ideas Axon is normally used for which makes your question a bit vague. Or, perchance, you are using it differently than normally intended.
That Axon supports CQRS through this approach, does not necessitate that you do CQRS within your set up as well, by the way.
At any note, it would be good too (as also stated in the comments):
Include code snippets of the message handlers when these prove useful
Give some deeper insight in your configuration
Whether you aim to use the CQRS pattern in your application, yes or no
Completely separate from this, I can give some guidance on how Axon deals with transactions. Every message inside an Axon application will start a so-called "Unit of Work". It is the UnitOfWork (UoW for short) that will start a transaction. This means that no matter if you use commands, events or queries, Axon will have started that transaction for you already.
Taking this a step further, this also means that whatever you do inside a message handling function (thus the #CommandHandler, #EventHandler and #QueryHandler annotated methods) will always already have an active transaction running. That for example defines that you do not have to include your own transaction management inside a message handling function, with for example the #Transactional annotation.
Concluding, I am guessing you might be mixing some concepts. This can obviously happen, so no worries there; that's what SO is for. Next to this though, you thus do not have to start your own transaction inside any message handling function, as you already have an active transaction at that point in time.
I have configured two databases. One for read (Read-Only), other for Read-Write operations. I have service which involves both read and write operations. I would like to use the read-only db for all read operations and the other db for write operations. How could I achieve this with Spring transactions. I've implemented annotation based approach which changes the datasource using AbstractRoutingDataSource. But, everytime I need to create a new transation using propogation=Requires_New. Is there a better way to do this?
#DbSource(DbType.READ_REPLICA)
#Transactional(propogation=Requires_New)
public Object readData(long id) {
return dataDao.find(id);
}
You should create seperate spring configurations for both of your datastores together with TransactionManager beans. At least one of these beans should have name value so you can use proper transactional manager when needed:
#Transactional(transactionManager="DS1transactionManagerBeanName")
// DS1dataStoreRelevant class/method
Of course combining logic which uses both data stores in single transaction is not possible with JpaTransactionManager. If this is what you are looking for you should consider using distributed JtaTransactionManager provided by web container like IBM WebSphere or other like Atomikos/Bitronix etc. which provides you with transactionality between different data stores (XA resources in general).
Some possible workaround in certain cases (like Oracle datastores) would be to provide visibility from one database to other and use single data store/transaction manager but I am not entirely sure how it works underneath on the database side.
The most basic solution would be just to not mix logic impacting each of the data store and arrange it in sequential transactions but as said whole chain of operations won't be transnational itself so possible rollback would apply only to current transaction (no rollback to the ones committed earlier). It would require some extra logic to introduce rollback/retry policy with dirty flags etc.
I have a code in my business layer that updates data on database and also in a rest service.
The question is that if it doesn't fail data must be save in both places and, in other hand, if it fails it must to rollback in database and send another requisition to rest api.
So, what I'm looking for is a way to use transaction management of EJB to also orchestrait calls to api. When in commit time, send a set requisition to api and, when in rollback time, send delete requisition to api.
In fact I need to maintain consistency and make both places syncronous.
I have read about UserTransactions and managedbeans but I don't have a clue about what is the best way to do that.
You can use regular distributed transactions, depending on your infrastructure and participants. This might be possible e.g. if all participants are EJBs and the data stores are capable to handle distributed transactions.
This won't work with loosely coupled componentes, and your setup looks like this.
I do not recommend to create your own distributed transaction protocol. Regarding the edge and corner cases, you will probably not end up with consistent data in the end.
I would suggest to think about using event sourcing and eventually consistency for things like that. For example, you could emit an event (command) for writing data. If your "rollback" is needed, you can emit an event (command) to delete the date written before. After all events are processed, the data is consistent.
Some interesting links might be:
Martin Fowler - Event Sourcing
Martin Fowler - CQRS
Apache Kafka
I had tried to terminate that by myself, but i can't.
I need to save objects in multiple relative tables of my database and it must be in one single transaction.
I am using Servlets, JSP, JDBC.
(already have the dao layer and service layer)
As we know, the transactions always must to be in the service layer.
When I was using Spring MVC, I always used this annotation in services:
#Transactional
and had options for TransactionManager in my spring.xml
Now I need to do the same with servlets.
Can anyone help me with some small example for servlets transactions or maybe somebody have suggestive thoughts for this?
You have different ways to manage transactions at JDBC level.
The simplest way, is a filter: you open a transaction at the beginning or the request processing and commit (or rollback) it at the end. It is as little invasive as possible in other layers, but you cannot have the transaction demarcation at the service layer.
At the opposite, you can add code to explicitely create and commit transactions in all (relevant) service methods. You can put real code in common methods to limit code duplication, but you will have to consistently modify all your service layer.
An alternate way, as you have an existant service layer, would be to mimic Spring and use proxies around your service classes. The proxies would open create transaction, call the real method and commit the transaction. IMHO, it would still be a little invasive method with little code duplication.
My choice would be to use method 1 for very simple use cases or prototyping and method 3 for more serious ones - but this is just my opinion.
I think first of all you need to understand which specification you would like to work with and then figure out how to do the integration.
There are so many techniques and technologies in Java to access the database.
In general if you want to access the DB at the lowest layer (JDBC) you'll have to manage transactions by yourself.
This link can be useful, because it provides a lot of examples. In general you have setAutoCommit(false)' and thenrollback/commitonConnection` jdbc interface.
If you wish to use stuff like hibernate (note, you still don't need spring for this) - the Transaction inteface can be handy.
Here is the Example
Spring as an integration framework allows using transaction management by means of definition of relevant beans, so you kind of chose by yourself which transaction management technology should be used.
This is a broad topic, you might be interested to read This to understand more the spring way to manage transactions.
In general, JDBC is the most low level of accessing the database in java, all other APIs are built on top of it.
Hope this helps
On your Service Method you should handle transaction yourself, you'll find below an example:
try {
dbConnection = getDBConnection();
dbConnection.setAutoCommit(false);
// do your database work preparedStatement Insert, Update
//OR
// If you are doing your work on DAO you can pass connection to your DAO
//XDao xDao = new XDao(dbConnection);
//YDao yDao = new YDao(dbConnection);
//xDao.doWork();
//yDao.doWork()
dbConnection.commit();
System.out.println("Done!");
} catch (SQLException e) {
System.out.println(e.getMessage());
dbConnection.rollback();
} finally {
//Close prepared statements
//close connection
if (dbConnection != null) {
dbConnection.close();
}
}
For advanced Pattern and uderstanding, I recommend this blog post here
I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern. Plus I have a lot of DAOs and me not willing to write the same save method for all the DAOs I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated and on production, the is StaleObjectException and duplicated data right, and i have the feeling that it's time to review what I've done, simplify it and make it more robust for large data handling. One thing you should know is that one request involves many DAO's.
There is quartz running for some updates in the database.
As much as I want to tune everything for the better I lack time to do the necessary research plus Hibernate is kind of huge (learning).
So this is it, I'll like to borrow your experience and ask for few question to know what direction to take.
Question 1 : is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?
Question 2 what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)
Question 3 : will HIbernateTemplate do for the simplest solution approach?
Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?
Please do no hesitate to point me to blogs or resources online , all that I need is a approach that works for my scenario. your approach if you were to do this.
Thanks for reading this, everybody's idea is welcomed...
I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern.
You should just drop all this code and use Spring/Hibernate APIs instead: less bugs, less maintenance.
I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated (...)
You can use a GenericDao and inject the required stuff with Spring.
Question 1: is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?
To strictly answer your question, here is what Reference Guide writes about the uuid generator:
5.1.4.1. Generator
...
uuid
uses a 128-bit UUID algorithm to
generate identifiers of type string
that are unique within a network (the
IP address is used). The UUID is
encoded as a string of 32 hexadecimal
digits in length.
So I consider it as safe. But I think your StaleObjectException are unrelated (it's another problem).
Question 2: what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)
The best strategy is to just use it, sessionFactory.getCurrentSession() will always give you a Session scoped to the current database transaction aka a "contextual session". Again, quoting the Reference Documentation:
2.5. Contextual sessions
Most applications using Hibernate need
some form of "contextual" session,
where a given session is in effect
throughout the scope of a given
context. However, across applications
the definition of what constitutes a
context is typically different;
different contexts define different
scopes to the notion of current.
Applications using Hibernate prior to
version 3.0 tended to utilize either
home-grown ThreadLocal-based
contextual sessions, helper classes
such as HibernateUtil, or utilized
third-party frameworks, such as Spring
or Pico, which provided
proxy/interception-based contextual
sessions.
(...)
However, as of version 3.1, the
processing behind
SessionFactory.getCurrentSession()
is now pluggable. To that end, a new
extension interface,
org.hibernate.context.CurrentSessionContext,
and a new configuration parameter,
hibernate.current_session_context_class,
have been added to allow pluggability
of the scope and context of defining
current sessions.
See the Javadocs for the
org.hibernate.context.CurrentSessionContext
interface for a detailed discussion of
its contract. It defines a single
method, currentSession(), by which
the implementation is responsible for
tracking the current contextual
session. Out-of-the-box, Hibernate
comes with three implementations of
this interface:
org.hibernate.context.JTASessionContext:
current sessions are tracked and
scoped by a JTA transaction. The
processing here is exactly the same as
in the older JTA-only approach. See
the Javadocs for details.
org.hibernate.context.ThreadLocalSessionContext:
current sessions are tracked by thread
of execution. See the Javadocs for
details.
org.hibernate.context.ManagedSessionContext:
current sessions are tracked by thread
of execution. However, you are
responsible to bind and unbind a
Session instance with static methods
on this class: it does not open,
flush, or close a Session.
(...)
There is no need to implement your own ThreadLocal-based solution nowadays, don't do that.
Question 3 : will HIbernateTemplate do for the simplest solution approach?
Well, the HibernateTemplate is not deprecated but it is not recommended anymore and I prefer to implement template-less DAOs:
public class ProductDaoImpl implements ProductDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Collection loadProductsByCategory(String category) {
return this.sessionFactory.getCurrentSession()
.createQuery("from test.Product product where product.category=?")
.setParameter(0, category)
.list();
}
}
Where the SessionFactory is injected by Spring. I suggest to read So should you still use Spring's HibernateTemplate and/or JpaTemplate?? for complete background and also the whole section 13.3. Hibernate in the Spring documentation on ORM Data Access.
Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?
Hmm... What? I would never implement my connection pool but use the one from my application server. Maybe you should clarify this question.
Update: In production, I wouldn't use Hibernate built-in connection pool but configure Hibernate to use an application server provided JNDI datasource (and thus the application server connection pool). From the documentation:
3.3. JDBC connections
...
Here is an example hibernate.properties file for an application server provided JNDI datasource:
hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = \
org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = \
org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
JDBC connections obtained from a JNDI datasource will automatically participate in the container-managed transactions of the application server.