How to create transaction handling by only using servlets and jdbc? - java

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

Related

Shared transaction between multiple applications

we got a requirement of create a transactional operation but handled through multiple applications.
I'm familiar with #Transactional annotation to achieve transactions, or for example using it programmatically like:
#Autowired
private EntityManagerFactory emf;
public void doSomething() {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.createNativeQuery("...do something...").executeUpdate();
tx.commit();
em.close();
}
So, if I need to allow an app to create a transaction dynamically I could pass em as parameter and populate multiple operations from different methods.
However, we got a weird requirement to achieve something like above code but involving multiple applications that share the same database, it would be like a distributed transaction.
Is this feasible with Spring? I'm not sure if I might create some rest services where one of the parameters are the serialized entity managers, although this looks very weird to me. Is it possible to handle like a shared transaction populating operations through multiple apps?
You may involve XA Transactions over JTA. You can use Spring support for JTA which implies use of particular JTA Transaction Manager implementation under the hood such as Atomikos (paid) or Bitronix (Apache-licensed, issues with maintenance now).
Some good overview is also available here, especially describing the alternatives to XA, including description of eventual consistency
Spring Boot + Atomikos sample on Github can demonstrate basics of JTA configuration within single application.
Once you get familiar with all of that, you may have similar question as in this thread. Note, that latter is raised 4 years ago and nothing has changed drastically since that time, so the answers there are still good.
In general, development and implementation of distributed ACID transactions across several applications/services can be a really challenging epic, often comparable by level of effort with re-architecting the whole solution in order to avoid XA usage at all.

What is the real delivered value of JTA?

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.

Where is the best place to begin transaction using Hibernate in a tired web application with Struts 2?

I got this Java web application which uses Struts 2 and Hibernate. In the most upper layer comprises of the Struts 2 action classes. Then there are my business logic classes which are responsible for the logic of the application. Finally there is a DAO layer (called Database Bridge) which is responsible for communicating with the database.
Currently I open sessions and do the transactions in DAO layer like this:
public static void saveObject(Object object) throws Exception {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(object);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
throw e;
} finally {
if (session != null)
if (session.isOpen())
session.getTransaction().rollback();
}
}
There seems to be some problems with this approach:
Logically my transactions are my Struts 2 actions (controllers) which should be either committed or rolled back. A Struts 2 action may lead to more than one DAO call, so it is possible that some parts of a logical transaction get committed and the rest of it get rolled back which hurts data integrity.
Some objects contain some lazy collections. If we do the transactions in the DAO layer, we need to initialize those collections there which is not an efficient way. because we don't need to load the collections in every action. So whenever an action needs a lazy collection we need to open a session in the action and load the lazy collection in there, which is a dirty solution.
I think it's better to avoid doing the transactions in the DAO layer. If we place the transactions in the Struts 2 action they are treated as atomic transactions and data consistency will be maintained. on the other hand whenever we need a lazy collection we can initialize it inside the action.
In order to keep the code clean, I will keep the DAO layer the same as before, but the methods in the DAO will get the session as a parameter from the upper layer and they won't deal with the commitment of transactions and sessions.
How does this strategy sound? is there any significant flaw in this approach? where do you think is the best place to start transactions and manage sessions?
It seems you are thinking in right direction but you should keep in mind that sessions in Hibernate are independent from transactions. Look at the transaction strategy configuration that could apply to your application.
Then you should read this article how the sessions and transactions work together.
Lately you might follow the Generic DAO approach don't know why but this technique is very popular.
And finally all of the above is already implemented by the Struts2 jQuery Grid. Look at this answer.
Seems all of the above are independent from Spring, if you like the Spring to manage transactions then you should go here.

Create Hibernate-Session per Request

I just started a simple Java testproject which manages some entities using Hibernate and provides a REST interface to manipulate these objects and provide some additional business logic. The REST interface is created using RESTEasy and Jetty.
Everything works fine so far, but I have the feeling that I'm actually writing too much boilerplate code. As I don't have much experience in these Java frameworks I'm just wondering if anyone could give me a hint on how to improve the situation.
Creting Hibernate Sessions per Request
Well, as far as I understood I have to create a Hibernate session per request and at the end I have to close it. So currently all of my service methods look like this:
Session session = HibernateUtil.getInstance().getSessionFactory().openSession();
...
...
...
session.close();
Is there any way to remove these two lines in order to somehow do this automatically?
Currently my service is registered as a RestEASY singleton. Will changing to a RESTeasy ressource and creating the session in the constructor solve the problem? I think it will solve the problem of creating the session. But wherer to close it?
In C++ this can easily done be creating a scoped object which closes the session at the end. But in Java?
Whenever such a REST request is made I have to check for a valid session (the user has to login previously). Is a ServletFilter the right way to do this?
General: Are there any other patterns or frameworks I should consider using? I mean I want to keep it as simple as possible and especially as I dont have that much experience I dont want to end up using Spring or whatever heavyweight framework. Seems that I'm used to the simplicity of Python and Django but for this little project I have to use Java.
THanks so far!
Hibernate's current recommended approach for managing Sessions is detailed on this wiki page. In particular, I think you need to read the last paragraph: This is all very difficult, can't this be done easier?
In the end, you do need to tell the persistence layer that "I'm about to do something" (which usually also gets the Session to do it with) and "I'm done doing it". You can do it with annotations, or JTA transactions, but that information still has to be communicated!
Inject SessionFactory to your Data Access Object and use sessionFactory.getCurrentSession() to access Hibernate Session object.
you can make use of any of the Factory classes available to implement this..
Then your code should look like this..
sessionFactory.getCurrentSession().save(newInstance);
You should try writing a Filter that does this. Spring's OpenSessionInViewFilter is a good place to start if you need an example.

Multiple transaction managers in spring and select one at runtime

For each client, I have separate databases but business logic and tables are same for each client. I want common service and dao layer for each client. In dao, I select datasource based on logged user client. In #Transactional, I have to pass bean id of transaction manager. How to make common service layer with #Transactional annotation.
Same question is here
Multiple transaction managers - Selecting a one at runtime - Spring
Choose between muliple transaction managers at runtime
but nobody reply
If you want to create a database connection dynamically, then have a look at this SO post.
From the post linked : Basically in JDBC most of these properties are not configurable in the
API like that, rather they depend on implementation. The way JDBC
handles this is by allowing the connection URL to be different per
vendor.
So what you do is register the driver so that the JDBC system can know
what to do with the URL:
DriverManager.registerDriver((Driver)
Class.forName("com.mysql.jdbc.Driver").newInstance());
Then you form
the URL:
String url =
"jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"
And finally, use it to get a connection:
Connection c = DriverManager.getConnection(url);
In more
sophisticated JDBC, you get involved with connection pools and the
like, and application servers often have their own way of registering
drivers in JNDI and you look up a DataSource from there, and call
getConnection on it.
In terms of what properties MySQL supports, see here (The link is dead).
EDIT: One more thought, technically just having a line of code which
does Class.forName("com.mysql.jdbc.Driver") should be enough, as the
class should have its own static initializer which registers a
version, but sometimes a JDBC driver doesn't, so if you aren't sure,
there is little harm in registering a second one, it just creates a
duplicate object in memeory.
I don't know if this will work, since I have not tested it, but you
could try.
Now what you could do is, use the #Transactional annotation on top of the DAOs without specifying any values (That works). Now in your DAO classes, instead of injecting any DataSource bean, create your own dataSource dynamically as specified in the above link and then either inject that dependency at runtime, use getter setter methods, or just use the new keyword. I hope that'd do the trick.
NOTE: I have not tested it myself yet, so if this works, do let me know.
You do not need to configure and switch between multiple transaction managers to accomplish your end goal. Instead use the Spring provided org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource mechanism.
Detailed examples can be found here :
https://spring.io/blog/2007/01/23/dynamic-datasource-routing/
http://howtodoinjava.com/spring/spring-orm/spring-3-2-5-abstractroutingdatasource-example/

Categories