Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Dashboard
Bitronix Transaction Manager
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<h1>JTA Best Practices</h1> <p>Why is the JTA API your friend ? How does it help you write better code ? Those are questions that we will try to answer here. These best practices are not limited to BTM but are valid for all JTA implementations. The more you use JTA, the better the world will be.</p> <h4>Contents</h4> <img class="editor-inline-macro" src="/plugins/servlet/confluence/placeholder/macro?definition=e3RvYzptYXhMZXZlbD0zfG1pbkxldmVsPTJ9&locale=en_GB&version=2" data-macro-name="toc" data-macro-parameters="maxLevel=3|minLevel=2"> <h2>Why using the JTA API</h2> <p>Even if you're only planning to use a single database in your application (ie: if you don't plan to make use of 2 Phase Commit) using the JTA API is still a good idea as it helps separating concerns in your application.</p> <p>The biggest benefit is the separation of the transaction management concern from the connection management concern. What does that mean ?</p> <p>When using 'good old' JDBC, you work with a single object type: the <code>Connection</code> but this object is used twofolds: for data manipulation (ie: <code>SELECT, INSERT, UPDATE, DELETE</code>) and for transaction management (ie: <code>COMMIT and ROLLBACK</code>).</p> <p>This is awkward as you often end up using an object for a concern (data manipulation) then keep it aside for later usage for another concern (committing or rolling back your changes).</p> <h2>Straight JDBC Example</h2> <p>Take this simple example to illustrate our concern:</p> <h4>Example 1</h4> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> public void executeA_B_C() { executeBusinessLogicA(); executeBusinessLogicB(); executeBusinessLogicC(); } public void executeBusinessLogicA() { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here c.commit(); } catch(Exception ex) { c.rollback(); // exception handling } finally { c.close(); } } public void executeBusinessLogicB() { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here c.commit(); } catch(Exception ex) { c.rollback(); // exception handling } finally { c.close(); } } public void executeBusinessLogicC() { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here c.commit(); } catch(Exception ex) { c.rollback(); // exception handling } finally { c.close(); } } </pre></td></tr></table> <p>This code is reasonably clean as the calling business method (<code>executeA_B_C()</code>) does no know that the underlying logic is using JDBC which is good Object Oriented design. It is also possible to encapsulate the JDBC boilerplate code in some helper class, DAO or even delegate that to a more powerful solution like <a href="http://static.springframework.org/spring/docs/2.0.x/reference/jdbc.html">Spring's JdbcTemplate</a>. Data access code will change in that case but the idea stays the same.</p> <p>Unfortunately the data manipulation is not atomic: if an error happen in <code>executeBusinessLogicB</code> then all modifications made by <code>executeBusinessLogicA</code> cannot be rolled back.</p> <p>A commonly found way to fix this problem is by sharing the <code>Connection</code> object between all 3 business methods:</p> <h4>Example 2</h4> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> public void executeA_B_C() { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { executeBusinessLogicA(c); executeBusinessLogicB(c); executeBusinessLogicC(c); c.commit(); } catch(Exception ex) { c.rollback(); // exception handling } finally { c.close(); } } public void executeBusinessLogicA(Connection c) throws SQLException { // SELECT, INSERT, UPDATE or DELETE here } public void executeBusinessLogicB(Connection c) throws SQLException { // SELECT, INSERT, UPDATE or DELETE here } public void executeBusinessLogicC(Connection c) throws SQLException { // SELECT, INSERT, UPDATE or DELETE here } </pre></td></tr></table> <p>The code is now much less clean as to ensure all 3 business methods will execute in the same transaction, we pass them a <code>Connection</code> object which is not of any business value.</p> <h2>Best of both worlds</h2> <p>How to get the clean data access encapsulation of Example 1 together with correct transaction handling of the Example 2 ? A straightforward continuation of the same logic could lead us to some kind of <code>ConnectionHolder</code> singleton that would store the connection in a <code>ThreadLocal</code> variable. The different business methods would then get their <code>Connection</code> from the <code>ConnectionHolder</code> object.</p> <p>While this would work, this is not as trivial as it sounds. You would have to initialize the <code>ConnectionHolder</code> (or make it initialize lazily) then clean up all resources it holds together with exception handling. This also makes the code less reusable as you always need to ensure you have access to a <code>ConnectionHolder</code> from within your business methods.</p> <p>A better solution is to separate the transaction management logic from the data access logic, and this is exactly what JTA is for.</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> public void executeA_B_C() { UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction"); try { ut.begin(); executeBusinessLogicA(); executeBusinessLogicB(); executeBusinessLogicC(); ut.commit(); } catch(Exception ex) { ut.rollback(); // exception handling } } public void executeBusinessLogicA() throws SQLException { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here } finally { c.close(); } } public void executeBusinessLogicB() throws SQLException { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here } finally { c.close(); } } public void executeBusinessLogicC() throws SQLException { DataSource ds = (DataSource) ctx.lookup("jdbc/myds"); Connection c = myDataSource.getConnection(); try { // SELECT, INSERT, UPDATE or DELETE here } finally { c.close(); } } </pre></td></tr></table> <p>Not only is this code more maintainable than the previous example 2 but it also improves example one in two areas: not only is it now fully transactional but the error handling is now centralized.</p> <p>You don't have to care about connections, just get them from the pool when needed and release them as soon as you're done with it. The transaction manager and the connection pool will ensure the transaction will be committed at the right time.</p> <p>As long as you're sticking with a single database, you won't pay the extra 2PC costs as the 1PC optimization will kick in. You don't even need a database implementing <code>XADataSource</code> thanks to the <a class="confluence-link" href="/display/BTM/LastResourceCommit2x" data-linked-resource-id="183074847" data-linked-resource-type="page" data-linked-resource-default-alias="LastResourceCommit2x" data-base-url="http://docs.codehaus.org">Last Resource Commit</a> implementation.</p> <h2>Extra benefits</h2> <p>JTA not only allows you to cleanly separate our concerns, it also comes with extra benefits:</p> <ul> <li>2PC is right at the corner. In case you later on need to access two distinct databases or send/receive JMS messages atomically, you just have to add the extra logic you need without touching your transaction code as you've already taken care of it.</li> <li>Resources hog can be avoided. A timeout can be set on the transaction so that you're guaranteed your database connections can't be held more than a specified amount of time. Some transaction managers even offer a configurable default timeout value so you don't even have to change your code. BTM obviously <a href="http://docs.codehaus.org/display/BTM/Configuration2x#Configuration2x-Timerssettings">offers that</a>.</li> <li>Transactional safeguard. Some transaction managers can be configured so that usage of the pooled connections can only be done while a transaction is running. This allows you to guarantee that all your code is transactional. Once again, BTM implements such feature via its <a href="http://docs.codehaus.org/display/BTM/JdbcConfiguration2x#JdbcConfiguration2x-UsingtheBTMAPI">allowLocalTransactions datasource property</a>.</li> </ul> <h2>Other references</h2> <ul> <li>The Hibernate team also recommend to follow the pattern described above here: <a class="external-link" href="http://www.hibernate.org/42.html#A5" rel="nofollow">http://www.hibernate.org/42.html#A5</a> and there: <a class="external-link" href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/architecture.html#architecture-current-session" rel="nofollow">http://docs.jboss.org/hibernate/stable/core/reference/en/html/architecture.html#architecture-current-session</a><br /> <img class="confluence-embedded-image confluence-external-resource" src="http://www.bitronix.be/images/shim.gif" data-image-src="http://www.bitronix.be/images/shim.gif"></li> </ul>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced