`

How to use JDBC and transactions in Tomcat with JOTM Target audience This howt

    博客分类:
  • JAVA
 
阅读更多

How to use JDBC and transactions in Tomcat with JOTM

Target audience

This howto is intended to Servlet/JSP developpers using Tomcat who want to take advantage of distributed transactions when using JDBC code in their servlets

This howto was written based on the JNDI Datasource HOW-TO provided by Tomcat.

It has been written for:

  • Tomcat 4.1.18
  • JOTM 1.4

It has been successfully reported to work on

  • MySQL
    • version 4.0.12, using InnoDB
    • with mysql-connector-java version 2.0.14
  • PostgreSQL
    • version 7.3.1
    • with pg73jdbc2.jar

1. Introduction

JOTM (Java Open Transaction Manager) is a transaction manager written in Java and implementating JTA (Java Transaction API). It is an Open Source project released under LGPL.

Tomcat is the servlet container that is used in the official Reference Implementation for the Java Servlet and JavaServer Pages (JSP) technologies. Tomcat is released under the Apache Software License

MySQL configuration

Ensure that you follow these instructions as variations can cause problems.

Create a new test user, a new database and a single test table. Your MySQL user must have a password assigned. The driver will fail if you try to connect with an empty password.

mysql> GRANT ALL PRIVILEGES ON *.* TO mojo@localhost
    ->   IDENTIFIED BY 'jojo' WITH GRANT OPTION;
mysql> create database javatest;
mysql> use javatest;
mysql> create table testdata (
    ->   id int not null auto_increment primary key,
    ->   foo int)type=InnoDB;
mysql>

Note: the above user should be removed once testing is complete!

Next insert some test data into the testdata table.

mysql> insert into testdata values(null, 1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from testdata;
+----+-----+
| ID | FOO |
+----+-----+
|  1 |   1 |
+----+-----+
1 row in set (0.00 sec)

mysql>

PostgreSQL configuration is similar.

Installing Required JARs

In order for a web application to use JOTM, the webapp and Tomcat need to have access to the JOTM jars, as well as the jars it requires

Here is a list of the required jars. They are all included with JOTM 1.4 binary distribution, available at http://www.objectweb.org/jotm

  • in the lib/ directory
    • jotm.jar
    • jotm_jrmp_stubs.jar
    • jonas_timer.jar
    • carol.jar
    • jta-spec1_0_1.jar
    • jts1_0.jar
    • objectweb-datasource.jar
    • xapool.jar

All these jar files need to be placed on $TOMCAT_HOME/common/lib/ so that both Tomcat and your web application will see them.

You also need to copy the jar of your JDBC driver to $TOMCAT_HOME/common/lib/.

Configuring JOTM

You'll need to create a file named carol.properties with the following properties:

# lmi stands for Local Method Invocation (it's a "fake" RMI)
carol.protocols=lmi

# do not use CAROL JNDI wrapper
carol.start.jndi=false

# do not start a name server
carol.start.ns=false
    

this file needs to be placed on $TOMCAT_HOME/common/classes/ so that Tomcat and JOTM will see it.

Configuring Tomcat

server.xml configuration

Now that you've installed JOTM in Tomcat, you need to configure Tomcat so that it can access JDBC and transaction resources. This is done in the dbtest.xml file which will be used by Tomcat to initialize the resources used by your web application.

<Context path="/dbtest" docBase="dbtest.war" debug="0"
  reloadable="true" crossContext="true">
  <!-- Resource configuration for JDBC datasource
       use XAPool
  -->
  <Resource name="jdbc/myDB" auth="Container"
    type="javax.sql.DataSource"/>
  <ResourceParams name="jdbc/myDB">
    <parameter>
      <name>factory</name>
      <value>org.objectweb.jndi.DataSourceFactory</value>
    </parameter>
    <!-- configured by default for PostgreSQL, just change the values
         to set it for your database
    -->
    <parameter><name>username</name><value>mojo</value></parameter>
    <parameter><name>password</name><value>jojo</value></parameter>
    <parameter><name>driverClassName</name>
      <value>org.postgresql.Driver</value></parameter>
    <parameter><name>url</name>
      <value>jdbc:postgresql://localhost/javatest</value></parameter>
    <!--
       <parameter><name>driverClassName</name>
       <value>org.gjt.mm.mysql.Driver</value></parameter>
       <parameter><name>url</name>
       <value>jdbc:mysql://localhost/javatest</value></parameter>
    -->
  </ResourceParams>
  <!-- Resource configuration for UserTransaction
  use JOTM
  -->
  <Resource name="UserTransaction" auth="Container"
    type="javax.transaction.UserTransaction"/>
  <ResourceParams name="UserTransaction">
    <parameter>
      <name>factory</name>
      <value>org.objectweb.jotm.UserTransactionFactory</value>
    </parameter>
    <parameter>
      <name>jotm.timeout</name>
      <value>60</value>
    </parameter>
  </ResourceParams>
</Context>

web.xml configuration

Now you have to configure the web.xml file of your web application

<?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE web-app PUBLIC
	"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
	"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <resource-env-ref>
    <description>
      DB Connection
    </description>
    <resource-env-ref-name>
      jdbc/myDB
    </resource-env-ref-name>
    <resource-env-ref-type>
      javax.sql.DataSource
    </resource-env-ref-type>
  </resource-env-ref>
</web-app>

Test Code

Now create a simple test.jsp for use later.

<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>

    <%
    String completion = request.getParameter("completion");
    foo.DBTest test = new foo.DBTest();
    test.init(completion);
    %>
    <h2>Transaction completion</h2>
    Transaction completion is :<strong><%= completion %></strong>

    <h2>Results</h2>
    Int stored in JDBC : <strong><%= test.getFoo() %></strong><br />

    <hr />

    <form action="test.jsp" method="get">
      <input type="radio" name="completion" value="commit" checked="true"> Commit<BR>
      <input type="radio" name="completion" value="rollback">Rollback<BR>
      <button type="submit">Completion</button>
    </form>
  </body>
</html>

And create a Java class to actually use your new Datasource and transactions. Note: this code isn't anywhere near production ready - it's only supposed to be used as a simple test :-)

package foo;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;

public class DBTest{

    int foo = -1;
    // value stored in DB

    public void init(String completion) {
        try{
            Context ctx = new InitialContext();

            // JDBC stuff
            DataSource ds =
                (DataSource)ctx.lookup("java:comp/env/jdbc/myDB");

            UserTransaction ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction");

            java.sql.Connection conn = ds.getConnection();

            System.out.println("<<< beginning the transaction >>>");
            ut.begin();

             // JDBC statements
             Statement stmt = conn.createStatement();
             ResultSet rst =
                 stmt.executeQuery("select id, foo from testdata");
             if(rst.next()) {
                 foo=rst.getInt(2);
             }
             System.out.println("foo = "+ foo +" (before completion)");

             PreparedStatement pstmt = conn.prepareStatement("update testdata set foo=? where id=1");
             pstmt.setInt(1,++foo);
             pstmt.executeUpdate();

              if (completion != null && completion.equals("commit")) {
                  System.out.println("<<< committing the transaction >>>");
                  ut.commit();
              } else {
                  System.out.println("<<< rolling back the transaction >>>");
                  ut.rollback();
              }

             // we set foo to the value stored in the DB
             rst =
                 stmt.executeQuery("select id, foo from testdata");
             if(rst.next()) {
                 foo=rst.getInt(2);
             }
             System.out.println("foo = "+ foo +" (after completion)");

             conn.close();
             System.out.println("<<< done >>>");
        }catch(Exception e) {
            System.out.print("DBTest >> ");
            e.printStackTrace();
        }
    }

    public String getFoo() { return ""+foo; }
}

Finally deploy your web app into $CATALINA_HOME/webapps as a warfile called dbtest.war.

Once deployed, point a browser at http://localhost:8080/dbtest/test.jsp to view the fruits of your hard work.

分享到:
评论

相关推荐

    JDBC Developers Guide Reference.rar

    This chapter describes how to use the JDBC connections within a JTA global transaction in order to include all changes to multiple databases within a transaction. Chapter 18, "Advanced Topics" This ...

    High Performance in-memory computing with Apache Ignite.pdf

    This book covers a verity of topics, including in-memory data grid, highly available service grid, streaming (event processing for IoT and fast data) and in-memory computing use cases from high-...

    Building Blockchain Projects -Packt Publishing((2017).pdf )

    This book will teach you what Blockchain is, how it maintains data integrity, and how to create real- world Blockchain projects using Ethereum. With interesting real-world projects, you will know ...

    Oracle Database Transactions and Locking Revealed(Apress,2014).

    Read this short, 150-page book that is adapted from Expert Oracle Database Architecture to gain a solid and accurate understanding of how locking and concurrency are dealt with by Oracle Database....

    Building Blockchain Projects_Develop Real-Packt Publishing(2017)

    This book will teach you what Blockchain is, how it maintains data integrity, and how to create real- world Blockchain projects using Ethereum. With interesting real-world projects, you will know ...

    Beginning T-SQL with Microsoft SQL Server 2005 and 2008

    You will not only learn to use correct SQL syntax but will understand how this process works in simple terms. More advanced topics in the concluding section will teach you to create and manage T-SQL...

    Mastering Microservices with Java, 3rd Edition.epub

    Mastering Microservices with Java, 3rd ...By the end of this book, you’ll have learned how to build smaller, lighter, and faster services that can be implemented easily in a production environment.

    Cryptography in .NET Succinctly(SyncFusion,2015)

    This book is aimed at .NET developers who want to understand how to use cryptography in their applications. The user is expected to be reasonably experienced as a .NET developer but no prior knowledge...

    mysql-8-cookbook2018

    RDBMS and how to use MySQL for transactions. Chapter 6, Binary Logging, demonstrates how to enable binary logging, various formats of binary logs, and how to retrieve data from binary logs. Chapter 7,...

    Programming with Transactions SSD7Programming with Transactions

    Programming with Transactions Testing Commits and Rollbacks Almost all commercial-strength DBMS software supports the ability to undo the effects of a transaction before those effects are committed ...

    Expert Oracle Database Architecture 2nd 原版PDF by Kyte

    software, and from working with fellow Oracle developers to help them build reliable and robust applications based on the Oracle database. The book is basically a reflection of what I do every day and...

    SQL Server 2014 Development Essentials - Masood-Al-Farooq, Basit A. [SRG].pdf

    DML language elements in detail, and how you can use them to create, manage, and secure SQL Server 2014 databases, schemas, and tables. This chapter also shows you how you can use SQL Server ...

    atomikos-transactions-jdbc.jar.zip

    《Atomikos Transactions JDBC:分布式事务处理的利器》 在Java世界中,处理数据库事务时,我们经常会遇到分布式事务的需求,特别是在大型系统或者微服务架构中。Atomikos Transactions JDBC是一个强大的开源工具,...

    Redis-Essentials.pdf

    This chapter also shows how to use twemproxy to distribute Redis data across different instances transparently. Chapter 9, Redis Cluster and Redis Sentinel (Collective Intelligence), demonstrates the...

    JavaScript Applications with Node.js, React, React Native and MongoDB

    This book will teach you how to develop JavaScript applications with simple to use, yet powerful JavaScript technologies and host everything in the cloud in an economic and robust way in AWS. ...

    Entity.Framework.Core.Cookbook.2nd.Edition

    The book will then explain how to work with transactions and stored procedures along with improving Entity Framework using query libraries. Moving on, you will learn to improve complex query ...

    pro spring batch

    including transactions and job state/restartability * How to scale batch jobs via distributed batch processing * How to handle testing batch processes (Unit and functional) Who this book is for * Java...

Global site tag (gtag.js) - Google Analytics